aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/fan.c10
-rw-r--r--drivers/acpi/glue.c6
-rw-r--r--drivers/acpi/pci_slot.c5
-rw-r--r--drivers/acpi/processor_core.c5
-rw-r--r--drivers/acpi/processor_throttling.c17
-rw-r--r--drivers/acpi/scan.c2
-rw-r--r--drivers/acpi/sleep/main.c42
-rw-r--r--drivers/acpi/system.c1
-rw-r--r--drivers/acpi/thermal.c4
-rw-r--r--drivers/acpi/video.c5
-rw-r--r--drivers/atm/fore200e.c15
-rw-r--r--drivers/auxdisplay/cfag12864b.c13
-rw-r--r--drivers/base/Kconfig3
-rw-r--r--drivers/base/base.h27
-rw-r--r--drivers/base/class.c153
-rw-r--r--drivers/base/core.c196
-rw-r--r--drivers/base/cpu.c14
-rw-r--r--drivers/base/memory.c31
-rw-r--r--drivers/base/node.c15
-rw-r--r--drivers/base/power/trace.c2
-rw-r--r--drivers/base/sys.c64
-rw-r--r--drivers/base/topology.c17
-rw-r--r--drivers/block/aoe/aoechr.c5
-rw-r--r--drivers/block/paride/pg.c5
-rw-r--r--drivers/block/paride/pt.c10
-rw-r--r--drivers/block/pktcdvd.c4
-rw-r--r--drivers/char/Kconfig17
-rw-r--r--drivers/char/Makefile3
-rw-r--r--drivers/char/amiserial.c3
-rw-r--r--drivers/char/cyclades.c8
-rw-r--r--drivers/char/dsp56k.c3
-rw-r--r--drivers/char/epca.c58
-rw-r--r--drivers/char/esp.c5
-rw-r--r--drivers/char/hw_random/Kconfig13
-rw-r--r--drivers/char/hw_random/Makefile2
-rw-r--r--drivers/char/hw_random/n2-asm.S79
-rw-r--r--drivers/char/hw_random/n2-drv.c771
-rw-r--r--drivers/char/hw_random/n2rng.h118
-rw-r--r--drivers/char/ip2/ip2main.c12
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c2
-rw-r--r--drivers/char/isicom.c30
-rw-r--r--drivers/char/istallion.c41
-rw-r--r--drivers/char/keyboard.c2
-rw-r--r--drivers/char/lcd.c516
-rw-r--r--drivers/char/lcd.h154
-rw-r--r--drivers/char/lp.c3
-rw-r--r--drivers/char/mem.c13
-rw-r--r--drivers/char/misc.c4
-rw-r--r--drivers/char/mmtimer.c29
-rw-r--r--drivers/char/moxa.c3
-rw-r--r--drivers/char/mspec.c23
-rw-r--r--drivers/char/mxser.c49
-rw-r--r--drivers/char/n_hdlc.c4
-rw-r--r--drivers/char/nvram.c1
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c2
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c5
-rw-r--r--drivers/char/ppdev.c5
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/char/raw.c7
-rw-r--r--drivers/char/riscom8.c27
-rw-r--r--drivers/char/rocket.c5
-rw-r--r--drivers/char/rtc.c19
-rw-r--r--drivers/char/snsc.c3
-rw-r--r--drivers/char/specialix.c803
-rw-r--r--drivers/char/stallion.c21
-rw-r--r--drivers/char/sx.c3
-rw-r--r--drivers/char/synclink.c7
-rw-r--r--drivers/char/synclink_gt.c154
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/tty_io.c734
-rw-r--r--drivers/char/tty_ldisc.c714
-rw-r--r--drivers/char/vc_screen.c12
-rw-r--r--drivers/char/viotape.c8
-rw-r--r--drivers/char/vme_scc.c5
-rw-r--r--drivers/char/vt.c20
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c5
-rw-r--r--drivers/cpufreq/cpufreq.c59
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c4
-rw-r--r--drivers/cpufreq/cpufreq_stats.c24
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c79
-rw-r--r--drivers/cpufreq/freq_table.c12
-rw-r--r--drivers/cpuidle/sysfs.c10
-rw-r--r--drivers/dca/dca-core.c131
-rw-r--r--drivers/dca/dca-sysfs.c9
-rw-r--r--drivers/dma/Kconfig37
-rw-r--r--drivers/dma/Makefile3
-rw-r--r--drivers/dma/dmaengine.c35
-rw-r--r--drivers/dma/dmatest.c444
-rw-r--r--drivers/dma/dw_dmac.c1122
-rw-r--r--drivers/dma/dw_dmac_regs.h225
-rw-r--r--drivers/dma/fsldma.c38
-rw-r--r--drivers/dma/ioat.c15
-rw-r--r--drivers/dma/ioat_dca.c244
-rw-r--r--drivers/dma/ioat_dma.c402
-rw-r--r--drivers/dma/ioatdma.h28
-rw-r--r--drivers/dma/ioatdma_hw.h1
-rw-r--r--drivers/dma/ioatdma_registers.h20
-rw-r--r--drivers/dma/iop-adma.c53
-rw-r--r--drivers/dma/mv_xor.c1375
-rw-r--r--drivers/dma/mv_xor.h183
-rw-r--r--drivers/edac/cell_edac.c5
-rw-r--r--drivers/eisa/Makefile2
-rw-r--r--drivers/eisa/eisa-bus.c4
-rw-r--r--drivers/firmware/dcdbas.c3
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/max7301.c339
-rw-r--r--drivers/gpio/pcf857x.c33
-rw-r--r--drivers/hid/hid-core.c10
-rw-r--r--drivers/hid/hid-input-quirks.c40
-rw-r--r--drivers/hid/hid-input.c3
-rw-r--r--drivers/hid/hidraw.c53
-rw-r--r--drivers/hid/usbhid/hid-core.c2
-rw-r--r--drivers/hid/usbhid/hid-quirks.c22
-rw-r--r--drivers/hid/usbhid/hiddev.c14
-rw-r--r--drivers/hid/usbhid/usbkbd.c10
-rw-r--r--drivers/hid/usbhid/usbmouse.c8
-rw-r--r--drivers/hwmon/hdaps.c2
-rw-r--r--drivers/hwmon/hwmon.c3
-rw-r--r--drivers/i2c/i2c-core.c6
-rw-r--r--drivers/i2c/i2c-dev.c6
-rw-r--r--drivers/ide/Kconfig2
-rw-r--r--drivers/ide/arm/icside.c71
-rw-r--r--drivers/ide/arm/ide_arm.c14
-rw-r--r--drivers/ide/arm/palm_bk3710.c30
-rw-r--r--drivers/ide/arm/rapide.c24
-rw-r--r--drivers/ide/h8300/ide-h8300.c48
-rw-r--r--drivers/ide/ide-atapi.c58
-rw-r--r--drivers/ide/ide-cd.c157
-rw-r--r--drivers/ide/ide-cd.h38
-rw-r--r--drivers/ide/ide-cd_ioctl.c35
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-dma.c103
-rw-r--r--drivers/ide/ide-floppy.c90
-rw-r--r--drivers/ide/ide-generic.c73
-rw-r--r--drivers/ide/ide-io.c42
-rw-r--r--drivers/ide/ide-iops.c230
-rw-r--r--drivers/ide/ide-lib.c17
-rw-r--r--drivers/ide/ide-pnp.c29
-rw-r--r--drivers/ide/ide-probe.c366
-rw-r--r--drivers/ide/ide-proc.c4
-rw-r--r--drivers/ide/ide-tape.c137
-rw-r--r--drivers/ide/ide-taskfile.c38
-rw-r--r--drivers/ide/ide.c49
-rw-r--r--drivers/ide/legacy/buddha.c24
-rw-r--r--drivers/ide/legacy/falconide.c56
-rw-r--r--drivers/ide/legacy/gayle.c39
-rw-r--r--drivers/ide/legacy/ide-4drives.c20
-rw-r--r--drivers/ide/legacy/ide-cs.c54
-rw-r--r--drivers/ide/legacy/ide_platform.c32
-rw-r--r--drivers/ide/legacy/macide.c15
-rw-r--r--drivers/ide/legacy/q40ide.c47
-rw-r--r--drivers/ide/mips/au1xxx-ide.c56
-rw-r--r--drivers/ide/mips/swarm.c24
-rw-r--r--drivers/ide/pci/aec62xx.c5
-rw-r--r--drivers/ide/pci/alim15x3.c12
-rw-r--r--drivers/ide/pci/amd74xx.c1
-rw-r--r--drivers/ide/pci/cmd640.c29
-rw-r--r--drivers/ide/pci/cmd64x.c12
-rw-r--r--drivers/ide/pci/cs5520.c41
-rw-r--r--drivers/ide/pci/cs5535.c3
-rw-r--r--drivers/ide/pci/delkin_cb.c25
-rw-r--r--drivers/ide/pci/hpt34x.c1
-rw-r--r--drivers/ide/pci/hpt366.c23
-rw-r--r--drivers/ide/pci/ns87415.c115
-rw-r--r--drivers/ide/pci/pdc202xx_old.c3
-rw-r--r--drivers/ide/pci/piix.c4
-rw-r--r--drivers/ide/pci/scc_pata.c139
-rw-r--r--drivers/ide/pci/serverworks.c4
-rw-r--r--drivers/ide/pci/sgiioc4.c65
-rw-r--r--drivers/ide/pci/siimage.c6
-rw-r--r--drivers/ide/pci/sl82c105.c4
-rw-r--r--drivers/ide/pci/tc86c001.c16
-rw-r--r--drivers/ide/pci/via82cxxx.c1
-rw-r--r--drivers/ide/ppc/pmac.c222
-rw-r--r--drivers/ide/setup-pci.c109
-rw-r--r--drivers/ieee1394/dv1394.c7
-rw-r--r--drivers/ieee1394/iso.c1
-rw-r--r--drivers/ieee1394/nodemgr.c23
-rw-r--r--drivers/ieee1394/raw1394.c4
-rw-r--r--drivers/ieee1394/video1394.c6
-rw-r--r--drivers/infiniband/core/cm.c72
-rw-r--r--drivers/infiniband/core/cma.c99
-rw-r--r--drivers/infiniband/core/iwcm.c3
-rw-r--r--drivers/infiniband/core/sa_query.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c8
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c2
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.c1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c2
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c12
-rw-r--r--drivers/infiniband/hw/mlx4/main.c11
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h15
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c70
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c74
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c26
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c1
-rw-r--r--drivers/input/evbug.c12
-rw-r--r--drivers/input/evdev.c101
-rw-r--r--drivers/input/ff-memless.c4
-rw-r--r--drivers/input/gameport/emu10k1-gp.c2
-rw-r--r--drivers/input/gameport/gameport.c22
-rw-r--r--drivers/input/gameport/lightning.c2
-rw-r--r--drivers/input/gameport/ns558.c2
-rw-r--r--drivers/input/input.c2
-rw-r--r--drivers/input/joystick/a3d.c2
-rw-r--r--drivers/input/joystick/amijoy.c2
-rw-r--r--drivers/input/joystick/cobra.c2
-rw-r--r--drivers/input/joystick/db9.c2
-rw-r--r--drivers/input/joystick/gf2k.c2
-rw-r--r--drivers/input/joystick/grip.c2
-rw-r--r--drivers/input/joystick/grip_mp.c2
-rw-r--r--drivers/input/joystick/guillemot.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c2
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c8
-rw-r--r--drivers/input/joystick/iforce/iforce.h2
-rw-r--r--drivers/input/joystick/interact.c2
-rw-r--r--drivers/input/joystick/joydump.c2
-rw-r--r--drivers/input/joystick/magellan.c2
-rw-r--r--drivers/input/joystick/spaceball.c2
-rw-r--r--drivers/input/joystick/spaceorb.c2
-rw-r--r--drivers/input/joystick/stinger.c2
-rw-r--r--drivers/input/joystick/tmdc.c2
-rw-r--r--drivers/input/joystick/turbografx.c2
-rw-r--r--drivers/input/joystick/twidjoy.c4
-rw-r--r--drivers/input/joystick/warrior.c2
-rw-r--r--drivers/input/joystick/xpad.c12
-rw-r--r--drivers/input/keyboard/amikbd.c2
-rw-r--r--drivers/input/keyboard/atkbd.c46
-rw-r--r--drivers/input/keyboard/gpio_keys.c89
-rw-r--r--drivers/input/keyboard/hil_kbd.c1
-rw-r--r--drivers/input/keyboard/lkkbd.c6
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c15
-rw-r--r--drivers/input/keyboard/sunkbd.c2
-rw-r--r--drivers/input/keyboard/tosakbd.c2
-rw-r--r--drivers/input/keyboard/xtkbd.c2
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ati_remote.c18
-rw-r--r--drivers/input/misc/ati_remote2.c18
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c1
-rw-r--r--drivers/input/misc/keyspan_remote.c20
-rw-r--r--drivers/input/misc/powermate.c6
-rw-r--r--drivers/input/misc/sgi_btns.c178
-rw-r--r--drivers/input/misc/wistron_btns.c19
-rw-r--r--drivers/input/misc/yealink.c50
-rw-r--r--drivers/input/mouse/appletouch.c299
-rw-r--r--drivers/input/mouse/atarimouse.c27
-rw-r--r--drivers/input/mouse/hil_ptr.c37
-rw-r--r--drivers/input/mouse/inport.c2
-rw-r--r--drivers/input/mouse/logibm.c2
-rw-r--r--drivers/input/mouse/pc110pad.c2
-rw-r--r--drivers/input/mouse/sermouse.c2
-rw-r--r--drivers/input/serio/Kconfig10
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/ct82c710.c2
-rw-r--r--drivers/input/serio/hil_mlc.c6
-rw-r--r--drivers/input/serio/hp_sdc.c10
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h67
-rw-r--r--drivers/input/serio/libps2.c52
-rw-r--r--drivers/input/serio/q40kbd.c4
-rw-r--r--drivers/input/serio/rpckbd.c2
-rw-r--r--drivers/input/serio/serio.c9
-rw-r--r--drivers/input/serio/xilinx_ps2.c380
-rw-r--r--drivers/input/tablet/acecad.c4
-rw-r--r--drivers/input/tablet/aiptek.c6
-rw-r--r--drivers/input/tablet/gtco.c2
-rw-r--r--drivers/input/tablet/kbtab.c6
-rw-r--r--drivers/input/tablet/wacom.h2
-rw-r--r--drivers/input/tablet/wacom_sys.c6
-rw-r--r--drivers/input/tablet/wacom_wac.c39
-rw-r--r--drivers/input/touchscreen/Kconfig46
-rw-r--r--drivers/input/touchscreen/Makefile4
-rw-r--r--drivers/input/touchscreen/gunze.c2
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c2
-rw-r--r--drivers/input/touchscreen/htcpen.c255
-rw-r--r--drivers/input/touchscreen/inexio.c207
-rw-r--r--drivers/input/touchscreen/migor_ts.c250
-rw-r--r--drivers/input/touchscreen/touchit213.c234
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c42
-rw-r--r--drivers/input/touchscreen/wm9712.c18
-rw-r--r--drivers/isdn/capi/capi.c6
-rw-r--r--drivers/isdn/gigaset/asyncdata.c3
-rw-r--r--drivers/isdn/gigaset/bas-gigaset.c12
-rw-r--r--drivers/isdn/gigaset/common.c2
-rw-r--r--drivers/isdn/gigaset/gigaset.h3
-rw-r--r--drivers/isdn/gigaset/i4l.c56
-rw-r--r--drivers/isdn/gigaset/interface.c25
-rw-r--r--drivers/isdn/gigaset/usb-gigaset.c7
-rw-r--r--drivers/leds/Kconfig16
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-triggers.c3
-rw-r--r--drivers/leds/leds-atmel-pwm.c2
-rw-r--r--drivers/leds/leds-h1940.c9
-rw-r--r--drivers/leds/leds-pca9532.c337
-rw-r--r--drivers/leds/leds-pca955x.c384
-rw-r--r--drivers/macintosh/adb.c3
-rw-r--r--drivers/macintosh/adbhid.c61
-rw-r--r--drivers/mca/mca-bus.c2
-rw-r--r--drivers/md/bitmap.c54
-rw-r--r--drivers/md/dm-crypt.c18
-rw-r--r--drivers/md/dm-linear.c38
-rw-r--r--drivers/md/dm-log.c4
-rw-r--r--drivers/md/dm-mpath.c10
-rw-r--r--drivers/md/dm-snap.c163
-rw-r--r--drivers/md/dm-snap.h11
-rw-r--r--drivers/md/dm-table.c13
-rw-r--r--drivers/md/dm.c46
-rw-r--r--drivers/md/dm.h6
-rw-r--r--drivers/md/faulty.c2
-rw-r--r--drivers/md/linear.c20
-rw-r--r--drivers/md/md.c615
-rw-r--r--drivers/md/multipath.c17
-rw-r--r--drivers/md/raid0.c8
-rw-r--r--drivers/md/raid1.c30
-rw-r--r--drivers/md/raid10.c22
-rw-r--r--drivers/md/raid5.c745
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-dvb.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ioread.c1
-rw-r--r--drivers/media/video/uvc/uvc_queue.c1
-rw-r--r--drivers/media/video/videobuf-core.c1
-rw-r--r--drivers/memstick/host/jmb38x_ms.c4
-rw-r--r--drivers/message/fusion/mptbase.c3
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptfc.c4
-rw-r--r--drivers/message/i2o/device.c54
-rw-r--r--drivers/mfd/Kconfig11
-rw-r--r--drivers/mfd/Makefile4
-rw-r--r--drivers/mfd/mfd-core.c114
-rw-r--r--drivers/mfd/tc6393xb.c600
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/atmel_pwm.c3
-rw-r--r--drivers/misc/hpilo.c768
-rw-r--r--drivers/misc/hpilo.h189
-rw-r--r--drivers/misc/phantom.c5
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c3
-rw-r--r--drivers/mmc/card/mmc_test.c225
-rw-r--r--drivers/mmc/card/queue.c97
-rw-r--r--drivers/mmc/host/au1xmmc.c54
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c50
-rw-r--r--drivers/mmc/host/sdhci.c167
-rw-r--r--drivers/mmc/host/sdhci.h7
-rw-r--r--drivers/mtd/devices/block2mtd.c8
-rw-r--r--drivers/mtd/maps/uclinux.c1
-rw-r--r--drivers/mtd/mtdchar.c9
-rw-r--r--drivers/mtd/nand/cmx270_nand.c79
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139too.c138
-rw-r--r--drivers/net/Kconfig25
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/arm/at91_ether.c41
-rw-r--r--drivers/net/arm/at91_ether.h1
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/arm/etherh.c6
-rw-r--r--drivers/net/atl1e/Makefile2
-rw-r--r--drivers/net/atl1e/atl1e.h503
-rw-r--r--drivers/net/atl1e/atl1e_ethtool.c405
-rw-r--r--drivers/net/atl1e/atl1e_hw.c664
-rw-r--r--drivers/net/atl1e/atl1e_hw.h793
-rw-r--r--drivers/net/atl1e/atl1e_main.c2599
-rw-r--r--drivers/net/atl1e/atl1e_param.c263
-rw-r--r--drivers/net/atlx/atl1.c3
-rw-r--r--drivers/net/au1000_eth.c5
-rw-r--r--drivers/net/bfin_mac.c1
-rw-r--r--drivers/net/bonding/bond_main.c3
-rw-r--r--drivers/net/cpmac.c2
-rw-r--r--drivers/net/dm9000.c15
-rw-r--r--drivers/net/e1000/e1000.h71
-rw-r--r--drivers/net/e1000/e1000_ethtool.c558
-rw-r--r--drivers/net/e1000/e1000_hw.c1373
-rw-r--r--drivers/net/e1000/e1000_main.c1490
-rw-r--r--drivers/net/e1000/e1000_osdep.h14
-rw-r--r--drivers/net/e1000/e1000_param.c16
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/net/fec.c54
-rw-r--r--drivers/net/fec_mpc52xx.c5
-rw-r--r--drivers/net/fs_enet/Makefile5
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c319
-rw-r--r--drivers/net/fs_enet/fs_enet.h4
-rw-r--r--drivers/net/fs_enet/mac-fcc.c67
-rw-r--r--drivers/net/fs_enet/mac-fec.c23
-rw-r--r--drivers/net/fs_enet/mac-scc.c37
-rw-r--r--drivers/net/fs_enet/mii-bitbang.c107
-rw-r--r--drivers/net/fs_enet/mii-fec.c144
-rw-r--r--drivers/net/gianfar.c123
-rw-r--r--drivers/net/gianfar.h12
-rw-r--r--drivers/net/gianfar_ethtool.c41
-rw-r--r--drivers/net/hamradio/bpqether.c2
-rw-r--r--drivers/net/hamradio/hdlcdrv.c1
-rw-r--r--drivers/net/hp-plus.c2
-rw-r--r--drivers/net/hp.c2
-rw-r--r--drivers/net/igb/igb_main.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/macb.c4
-rw-r--r--drivers/net/macvlan.c3
-rw-r--r--drivers/net/meth.c2
-rw-r--r--drivers/net/mlx4/cmd.c3
-rw-r--r--drivers/net/mlx4/eq.c1
-rw-r--r--drivers/net/mlx4/fw.c18
-rw-r--r--drivers/net/mlx4/fw.h2
-rw-r--r--drivers/net/mlx4/main.c2
-rw-r--r--drivers/net/mlx4/mlx4.h1
-rw-r--r--drivers/net/mlx4/mr.c49
-rw-r--r--drivers/net/mlx4/pd.c7
-rw-r--r--drivers/net/mv643xx_eth.c2
-rw-r--r--drivers/net/myri10ge/myri10ge.c62
-rw-r--r--drivers/net/ne.c2
-rw-r--r--drivers/net/ne2.c2
-rw-r--r--drivers/net/netxen/Makefile2
-rw-r--r--drivers/net/netxen/netxen_nic.h575
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c710
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c168
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h251
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c2196
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h60
-rw-r--r--drivers/net/netxen/netxen_nic_init.c806
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c220
-rw-r--r--drivers/net/netxen/netxen_nic_main.c1169
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c114
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h31
-rw-r--r--drivers/net/phy/marvell.c7
-rw-r--r--drivers/net/ppp_generic.c3
-rw-r--r--drivers/net/r6040.c445
-rw-r--r--drivers/net/r8169.c14
-rw-r--r--drivers/net/sfc/efx.c39
-rw-r--r--drivers/net/sfc/falcon.c12
-rw-r--r--drivers/net/sfc/net_driver.h5
-rw-r--r--drivers/net/sh_eth.c5
-rw-r--r--drivers/net/sky2.c5
-rw-r--r--drivers/net/smc91x.c94
-rw-r--r--drivers/net/smc91x.h76
-rw-r--r--drivers/net/sunhme.c4
-rw-r--r--drivers/net/tc35815.c1
-rw-r--r--drivers/net/tulip/de4x5.c16
-rw-r--r--drivers/net/tulip/de4x5.h3
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/ucc_geth.c1
-rw-r--r--drivers/net/usb/cdc_ether.c11
-rw-r--r--drivers/net/usb/rndis_host.c4
-rw-r--r--drivers/net/wan/cosa.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c3
-rw-r--r--drivers/net/wireless/ipw2200.c33
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c18
-rw-r--r--drivers/net/xen-netfront.c19
-rw-r--r--drivers/pci/dmar.c4
-rw-r--r--drivers/pci/hotplug/acpiphp.h4
-rw-r--r--drivers/pci/intel-iommu.c2
-rw-r--r--drivers/pci/pci.c38
-rw-r--r--drivers/pci/proc.c18
-rw-r--r--drivers/pcmcia/Kconfig3
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/electra_cf.c1
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c93
-rw-r--r--drivers/pcmcia/pxa2xx_palmtx.c118
-rw-r--r--drivers/power/Kconfig6
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/apm_power.c2
-rw-r--r--drivers/power/palmtx_battery.c198
-rw-r--r--drivers/power/power_supply_core.c4
-rw-r--r--drivers/rtc/Kconfig19
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c16
-rw-r--r--drivers/rtc/rtc-cmos.c294
-rw-r--r--drivers/rtc/rtc-dev.c58
-rw-r--r--drivers/rtc/rtc-ds1305.c847
-rw-r--r--drivers/rtc/rtc-m41t80.c20
-rw-r--r--drivers/rtc/rtc-m41t94.c173
-rw-r--r--drivers/rtc/rtc-omap.c21
-rw-r--r--drivers/rtc/rtc-pcf8583.c129
-rw-r--r--drivers/rtc/rtc-s3c.c89
-rw-r--r--drivers/rtc/rtc-vr41xx.c65
-rw-r--r--drivers/s390/char/raw3270.c14
-rw-r--r--drivers/s390/char/tape_class.c7
-rw-r--r--drivers/s390/char/vmur.c5
-rw-r--r--drivers/s390/net/claw.c2141
-rw-r--r--drivers/s390/net/ctcm_dbug.c29
-rw-r--r--drivers/s390/net/ctcm_dbug.h39
-rw-r--r--drivers/s390/net/ctcm_fsms.c402
-rw-r--r--drivers/s390/net/ctcm_main.c514
-rw-r--r--drivers/s390/net/ctcm_main.h31
-rw-r--r--drivers/s390/net/ctcm_mpc.c1110
-rw-r--r--drivers/s390/net/ctcm_mpc.h2
-rw-r--r--drivers/s390/net/qeth_l3_main.c2
-rw-r--r--drivers/sbus/char/uctrl.c16
-rw-r--r--drivers/sbus/char/vfc.h4
-rw-r--r--drivers/sbus/char/vfc_dev.c39
-rw-r--r--drivers/sbus/char/vfc_i2c.c12
-rw-r--r--drivers/sbus/dvma.c2
-rw-r--r--drivers/sbus/sbus.c6
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/hosts.c7
-rw-r--r--drivers/scsi/ide-scsi.c32
-rw-r--r--drivers/scsi/scsi_transport_fc.c9
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c8
-rw-r--r--drivers/scsi/sun_esp.c1
-rw-r--r--drivers/serial/8250.c25
-rw-r--r--drivers/serial/8250_gsc.c2
-rw-r--r--drivers/serial/8250_pci.c17
-rw-r--r--drivers/serial/Kconfig16
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c118
-rw-r--r--drivers/serial/dz.c24
-rw-r--r--drivers/serial/icom.c2
-rw-r--r--drivers/serial/mpsc.c148
-rw-r--r--drivers/serial/samsung.c2
-rw-r--r--drivers/serial/serial_core.c3
-rw-r--r--drivers/serial/serial_txx9.c2
-rw-r--r--drivers/serial/zs.c21
-rw-r--r--drivers/spi/Kconfig45
-rw-r--r--drivers/spi/au1550_spi.c207
-rw-r--r--drivers/spi/spi.c6
-rw-r--r--drivers/spi/spi_mpc83xx.c29
-rw-r--r--drivers/spi/spidev.c23
-rw-r--r--drivers/spi/xilinx_spi.c5
-rw-r--r--drivers/uio/Kconfig10
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio.c26
-rw-r--r--drivers/uio/uio_pdrv.c118
-rw-r--r--drivers/usb/atm/cxacru.c1
-rw-r--r--drivers/usb/atm/speedtch.c1
-rw-r--r--drivers/usb/class/cdc-acm.c186
-rw-r--r--drivers/usb/class/cdc-acm.h5
-rw-r--r--drivers/usb/class/cdc-wdm.c127
-rw-r--r--drivers/usb/core/devices.c4
-rw-r--r--drivers/usb/core/devio.c99
-rw-r--r--drivers/usb/core/driver.c168
-rw-r--r--drivers/usb/core/endpoint.c4
-rw-r--r--drivers/usb/core/file.c15
-rw-r--r--drivers/usb/core/hcd.c6
-rw-r--r--drivers/usb/core/hcd.h4
-rw-r--r--drivers/usb/core/hub.c536
-rw-r--r--drivers/usb/core/inode.c16
-rw-r--r--drivers/usb/core/message.c22
-rw-r--r--drivers/usb/core/usb.c7
-rw-r--r--drivers/usb/core/usb.h19
-rw-r--r--drivers/usb/gadget/Kconfig14
-rw-r--r--drivers/usb/gadget/Makefile13
-rw-r--r--drivers/usb/gadget/amd5536udc.c2
-rw-r--r--drivers/usb/gadget/at91_udc.c13
-rw-r--r--drivers/usb/gadget/cdc2.c246
-rw-r--r--drivers/usb/gadget/composite.c1041
-rw-r--r--drivers/usb/gadget/config.c76
-rw-r--r--drivers/usb/gadget/dummy_hcd.c4
-rw-r--r--drivers/usb/gadget/epautoconf.c1
-rw-r--r--drivers/usb/gadget/ether.c2631
-rw-r--r--drivers/usb/gadget/f_acm.c589
-rw-r--r--drivers/usb/gadget/f_ecm.c833
-rw-r--r--drivers/usb/gadget/f_loopback.c381
-rw-r--r--drivers/usb/gadget/f_rndis.c827
-rw-r--r--drivers/usb/gadget/f_serial.c296
-rw-r--r--drivers/usb/gadget/f_sourcesink.c587
-rw-r--r--drivers/usb/gadget/f_subset.c423
-rw-r--r--drivers/usb/gadget/file_storage.c4
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c2
-rw-r--r--drivers/usb/gadget/g_zero.h25
-rw-r--r--drivers/usb/gadget/gadget_chips.h23
-rw-r--r--drivers/usb/gadget/goku_udc.c2
-rw-r--r--drivers/usb/gadget/inode.c23
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c2
-rw-r--r--drivers/usb/gadget/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/ndis.h10
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c2
-rw-r--r--drivers/usb/gadget/printer.c11
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c8
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c1
-rw-r--r--drivers/usb/gadget/rndis.c421
-rw-r--r--drivers/usb/gadget/rndis.h9
-rw-r--r--drivers/usb/gadget/serial.c2315
-rw-r--r--drivers/usb/gadget/u_ether.c967
-rw-r--r--drivers/usb/gadget/u_ether.h127
-rw-r--r--drivers/usb/gadget/u_serial.c1246
-rw-r--r--drivers/usb/gadget/u_serial.h58
-rw-r--r--drivers/usb/gadget/zero.c1162
-rw-r--r--drivers/usb/host/ehci-au1xxx.c369
-rw-r--r--drivers/usb/host/ehci-dbg.c4
-rw-r--r--drivers/usb/host/ehci-fsl.c17
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c8
-rw-r--r--drivers/usb/host/ehci-orion.c8
-rw-r--r--drivers/usb/host/ehci-ps3.c2
-rw-r--r--drivers/usb/host/ehci-q.c17
-rw-r--r--drivers/usb/host/ehci.h5
-rw-r--r--drivers/usb/host/isp116x-hcd.c25
-rw-r--r--drivers/usb/host/isp1760-hcd.c81
-rw-r--r--drivers/usb/host/isp1760-hcd.h20
-rw-r--r--drivers/usb/host/isp1760-if.c37
-rw-r--r--drivers/usb/host/ohci-at91.c9
-rw-r--r--drivers/usb/host/ohci-au1xxx.c327
-rw-r--r--drivers/usb/host/ohci-dbg.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-omap.c2
-rw-r--r--drivers/usb/host/ohci-pnx4008.c28
-rw-r--r--drivers/usb/host/ohci-ppc-of.c2
-rw-r--r--drivers/usb/host/ohci-ps3.c2
-rw-r--r--drivers/usb/host/ohci-q.c3
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-ssb.c2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c44
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/u132-hcd.c2
-rw-r--r--drivers/usb/host/uhci-hub.c2
-rw-r--r--drivers/usb/misc/auerswald.c10
-rw-r--r--drivers/usb/misc/emi62.c2
-rw-r--r--drivers/usb/misc/ftdi-elan.c24
-rw-r--r--drivers/usb/misc/iowarrior.c8
-rw-r--r--drivers/usb/misc/rio500.c8
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c13
-rw-r--r--drivers/usb/misc/usblcd.c6
-rw-r--r--drivers/usb/mon/mon_bin.c5
-rw-r--r--drivers/usb/mon/mon_stat.c14
-rw-r--r--drivers/usb/serial/Kconfig8
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c19
-rw-r--r--drivers/usb/serial/airprime.c353
-rw-r--r--drivers/usb/serial/ark3116.c32
-rw-r--r--drivers/usb/serial/belkin_sa.c201
-rw-r--r--drivers/usb/serial/belkin_sa.h15
-rw-r--r--drivers/usb/serial/bus.c20
-rw-r--r--drivers/usb/serial/ch341.c10
-rw-r--r--drivers/usb/serial/console.c136
-rw-r--r--drivers/usb/serial/cp2101.c392
-rw-r--r--drivers/usb/serial/cyberjack.c176
-rw-r--r--drivers/usb/serial/cypress_m8.c703
-rw-r--r--drivers/usb/serial/cypress_m8.h2
-rw-r--r--drivers/usb/serial/digi_acceleport.c460
-rw-r--r--drivers/usb/serial/empeg.c257
-rw-r--r--drivers/usb/serial/ezusb.c22
-rw-r--r--drivers/usb/serial/ftdi_sio.c1247
-rw-r--r--drivers/usb/serial/ftdi_sio.h126
-rw-r--r--drivers/usb/serial/funsoft.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c400
-rw-r--r--drivers/usb/serial/generic.c122
-rw-r--r--drivers/usb/serial/hp4x.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c1964
-rw-r--r--drivers/usb/serial/io_tables.h6
-rw-r--r--drivers/usb/serial/io_ti.c1875
-rw-r--r--drivers/usb/serial/ipaq.c146
-rw-r--r--drivers/usb/serial/ipw.c294
-rw-r--r--drivers/usb/serial/ir-usb.c481
-rw-r--r--drivers/usb/serial/iuu_phoenix.c58
-rw-r--r--drivers/usb/serial/keyspan.c955
-rw-r--r--drivers/usb/serial/keyspan.h44
-rw-r--r--drivers/usb/serial/keyspan_pda.c233
-rw-r--r--drivers/usb/serial/kl5kusb105.c417
-rw-r--r--drivers/usb/serial/kobil_sct.c617
-rw-r--r--drivers/usb/serial/mct_u232.c364
-rw-r--r--drivers/usb/serial/mos7720.c308
-rw-r--r--drivers/usb/serial/mos7840.c557
-rw-r--r--drivers/usb/serial/navman.c10
-rw-r--r--drivers/usb/serial/omninet.c171
-rw-r--r--drivers/usb/serial/option.c168
-rw-r--r--drivers/usb/serial/oti6858.c255
-rw-r--r--drivers/usb/serial/pl2303.c140
-rw-r--r--drivers/usb/serial/safe_serial.c298
-rw-r--r--drivers/usb/serial/sierra.c95
-rw-r--r--drivers/usb/serial/spcp8x5.c73
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c449
-rw-r--r--drivers/usb/serial/usb-serial.c400
-rw-r--r--drivers/usb/serial/usb_debug.c10
-rw-r--r--drivers/usb/serial/visor.c384
-rw-r--r--drivers/usb/serial/whiteheat.c441
-rw-r--r--drivers/usb/serial/whiteheat.h78
-rw-r--r--drivers/usb/storage/datafab.c2
-rw-r--r--drivers/usb/storage/debug.c2
-rw-r--r--drivers/usb/storage/debug.h2
-rw-r--r--drivers/usb/storage/dpcm.c2
-rw-r--r--drivers/usb/storage/dpcm.h2
-rw-r--r--drivers/usb/storage/freecom.c2
-rw-r--r--drivers/usb/storage/freecom.h2
-rw-r--r--drivers/usb/storage/initializers.c2
-rw-r--r--drivers/usb/storage/initializers.h2
-rw-r--r--drivers/usb/storage/isd200.c8
-rw-r--r--drivers/usb/storage/jumpshot.c2
-rw-r--r--drivers/usb/storage/protocol.c2
-rw-r--r--drivers/usb/storage/protocol.h2
-rw-r--r--drivers/usb/storage/scsiglue.c53
-rw-r--r--drivers/usb/storage/scsiglue.h2
-rw-r--r--drivers/usb/storage/sddr09.c1
-rw-r--r--drivers/usb/storage/sddr09.h2
-rw-r--r--drivers/usb/storage/sddr55.c2
-rw-r--r--drivers/usb/storage/sddr55.h2
-rw-r--r--drivers/usb/storage/shuttle_usbat.c2
-rw-r--r--drivers/usb/storage/shuttle_usbat.h2
-rw-r--r--drivers/usb/storage/transport.c83
-rw-r--r--drivers/usb/storage/transport.h2
-rw-r--r--drivers/usb/storage/unusual_devs.h13
-rw-r--r--drivers/usb/storage/usb.c111
-rw-r--r--drivers/usb/storage/usb.h25
-rw-r--r--drivers/video/Kconfig53
-rw-r--r--drivers/video/Makefile5
-rw-r--r--drivers/video/acornfb.c1
-rw-r--r--drivers/video/amifb.c24
-rw-r--r--drivers/video/atafb.c7
-rw-r--r--drivers/video/atmel_lcdfb.c92
-rw-r--r--drivers/video/aty/aty128fb.c8
-rw-r--r--drivers/video/aty/atyfb_base.c100
-rw-r--r--drivers/video/aty/radeon_base.c20
-rw-r--r--drivers/video/aty/radeonfb.h2
-rw-r--r--drivers/video/backlight/Kconfig45
-rw-r--r--drivers/video/backlight/Makefile8
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c244
-rw-r--r--drivers/video/backlight/backlight.c1
-rw-r--r--drivers/video/backlight/ili9320.c330
-rw-r--r--drivers/video/backlight/ili9320.h80
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c116
-rw-r--r--drivers/video/backlight/platform_lcd.c172
-rw-r--r--drivers/video/backlight/vgg2432a4.c284
-rw-r--r--drivers/video/bf54x-lq043fb.c2
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/carminefb.c790
-rw-r--r--drivers/video/carminefb.h64
-rw-r--r--drivers/video/carminefb_regs.h159
-rw-r--r--drivers/video/cobalt_lcdfb.c371
-rw-r--r--drivers/video/console/fbcon.c8
-rw-r--r--drivers/video/console/fbcon.h8
-rw-r--r--drivers/video/console/mdacon.c4
-rw-r--r--drivers/video/fbmem.c15
-rw-r--r--drivers/video/fbmon.c2
-rw-r--r--drivers/video/fsl-diu-fb.c60
-rw-r--r--drivers/video/geode/lxfb.h2
-rw-r--r--drivers/video/geode/lxfb_ops.c28
-rw-r--r--drivers/video/hgafb.c36
-rw-r--r--drivers/video/imxfb.c1
-rw-r--r--drivers/video/neofb.c215
-rw-r--r--drivers/video/offb.c192
-rw-r--r--drivers/video/omap/dispc.c1
-rw-r--r--drivers/video/omap/omapfb_main.c1
-rw-r--r--drivers/video/ps3fb.c1
-rw-r--r--drivers/video/pxafb.c72
-rw-r--r--drivers/video/pxafb.h2
-rw-r--r--drivers/video/sa1100fb.c8
-rw-r--r--drivers/video/sa1100fb.h2
-rw-r--r--drivers/video/sh7760fb.c658
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c725
-rw-r--r--drivers/video/sis/init.h1
-rw-r--r--drivers/video/sis/init301.h1
-rw-r--r--drivers/video/sis/initextlfb.c1
-rw-r--r--drivers/video/sis/osdef.h1
-rw-r--r--drivers/video/sis/sis.h22
-rw-r--r--drivers/video/sis/sis_accel.c1
-rw-r--r--drivers/video/sis/sis_main.c44
-rw-r--r--drivers/video/sis/sis_main.h4
-rw-r--r--drivers/video/sis/vgatypes.h4
-rw-r--r--drivers/video/skeletonfb.c37
-rw-r--r--drivers/video/sm501fb.c329
-rw-r--r--drivers/video/tdfxfb.c8
-rw-r--r--drivers/video/tridentfb.c1350
-rw-r--r--drivers/video/uvesafb.c4
-rw-r--r--drivers/video/vfb.c14
-rw-r--r--drivers/video/vga16fb.c122
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/xen/balloon.c1
-rw-r--r--drivers/xen/events.c27
-rw-r--r--drivers/xen/manage.c10
-rw-r--r--drivers/zorro/zorro-sysfs.c1
770 files changed, 55701 insertions, 30762 deletions
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 55c17afbe66..2655bc1b4ee 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -263,22 +263,22 @@ static int acpi_fan_add(struct acpi_device *device)
goto end;
}
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev.bus_id, cdev->id);
+ dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
acpi_driver_data(device) = cdev;
result = sysfs_create_link(&device->dev.kobj,
&cdev->device.kobj,
"thermal_cooling");
if (result)
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&device->dev, "Failed to create sysfs link "
+ "'thermal_cooling'\n");
result = sysfs_create_link(&cdev->device.kobj,
&device->dev.kobj,
"device");
if (result)
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&device->dev, "Failed to create sysfs link "
+ "'device'\n");
result = acpi_fan_add_fs(device);
if (result)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 2f173e83f8a..084109507c9 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -146,8 +146,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
acpi_status status;
if (dev->archdata.acpi_handle) {
- printk(KERN_WARNING PREFIX
- "Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
+ dev_warn(dev, "Drivers changed 'acpi_handle'\n");
return -EINVAL;
}
get_device(dev);
@@ -195,8 +194,7 @@ static int acpi_unbind_one(struct device *dev)
/* acpi_bind_one increase refcnt by one */
put_device(dev);
} else {
- printk(KERN_ERR PREFIX
- "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
+ dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
}
return 0;
}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index b9ab030a52d..dd376f7ad09 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -6,8 +6,8 @@
* Thanks to Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> for code
* review and fixes.
*
- * Copyright (C) 2007 Alex Chiang <achiang@hp.com>
- * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
+ * Alex Chiang <achiang@hp.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -158,6 +158,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
if (IS_ERR(pci_slot)) {
err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot));
kfree(slot);
+ return AE_OK;
}
slot->root_handle = parent_context->root_handle;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ec0f2d581ec..e36422a7122 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -714,9 +714,8 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
goto end;
}
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev.bus_id, pr->cdev->id);
+ dev_info(&device->dev, "registered as cooling_device%d\n",
+ pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj,
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 0622ace0522..a2c3f9cfa54 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -827,6 +827,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr_declare(new_mask);
int ret;
if (!pr)
@@ -838,7 +839,8 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
* Migrate task to the cpu pointed by pr.
*/
saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ cpumask_of_cpu_ptr_next(new_mask, pr->id);
+ set_cpus_allowed_ptr(current, new_mask);
ret = pr->throttling.acpi_processor_get_throttling(pr);
/* restore the previous state */
set_cpus_allowed_ptr(current, &saved_mask);
@@ -987,6 +989,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
cpumask_t saved_mask;
+ cpumask_of_cpu_ptr_declare(new_mask);
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
@@ -1013,7 +1016,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
@@ -1025,7 +1028,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ cpumask_of_cpu_ptr_next(new_mask, pr->id);
+ set_cpus_allowed_ptr(current, new_mask);
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
@@ -1034,7 +1038,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it is necessary to set T-state for every affected
* cpus.
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@@ -1056,7 +1060,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ cpumask_of_cpu_ptr_next(new_mask, i);
+ set_cpus_allowed_ptr(current, new_mask);
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
@@ -1068,7 +1073,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
- for_each_cpu_mask(i, online_throttling_cpus) {
+ for_each_cpu_mask_nr(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f3132aa47a6..f6f52c1a2ab 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -471,7 +471,7 @@ static int acpi_device_register(struct acpi_device *device,
device->dev.release = &acpi_device_release;
result = device_add(&device->dev);
if(result) {
- printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id);
+ dev_err(&device->dev, "Error adding device\n");
goto end;
}
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 0489a7d1d42..d13194a031b 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -280,9 +280,36 @@ static struct platform_suspend_ops acpi_suspend_ops_old = {
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
+
+static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
+{
+ old_suspend_ordering = true;
+ return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Abit KN9 (nForce4 variant)",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+ DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
+ },
+ },
+ {},
+};
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
+static unsigned long s4_hardware_signature;
+static struct acpi_table_facs *facs;
+static bool nosigcheck;
+
+void __init acpi_no_s4_hw_signature(void)
+{
+ nosigcheck = true;
+}
+
static int acpi_hibernation_begin(void)
{
acpi_target_sleep_state = ACPI_STATE_S4;
@@ -316,6 +343,12 @@ static void acpi_hibernation_leave(void)
acpi_enable();
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
+ /* Check the hardware signature */
+ if (facs && s4_hardware_signature != facs->hardware_signature) {
+ printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
+ "cannot resume!\n");
+ panic("ACPI S4 hardware signature mismatch");
+ }
}
static void acpi_pm_enable_gpes(void)
@@ -516,6 +549,8 @@ int __init acpi_sleep_init(void)
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0;
+
+ dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled)
@@ -544,6 +579,13 @@ int __init acpi_sleep_init(void)
&acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1;
printk(" S4");
+ if (!nosigcheck) {
+ acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+ (struct acpi_table_header **)&facs);
+ if (facs)
+ s4_hardware_signature =
+ facs->hardware_signature;
+ }
}
#endif
status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index d8e3f153b29..91dec448b3e 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -26,6 +26,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <linux/string.h>
#include <asm/uaccess.h>
#include <acpi/acpi_drivers.h>
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 9adfd180df6..912703691d3 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1220,8 +1220,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
tz->tz_enabled = 1;
- printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
- tz->device->dev.bus_id, tz->thermal_zone->id);
+ dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
+ tz->thermal_zone->id);
return 0;
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e32b6c14d92..e8a51a1700f 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -772,9 +772,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
if (IS_ERR(device->cdev))
return;
- printk(KERN_INFO PREFIX
- "%s is registered as cooling_device%d\n",
- device->dev->dev.bus_id, device->cdev->id);
+ dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+ device->cdev->id);
result = sysfs_create_link(&device->dev->dev.kobj,
&device->cdev->device.kobj,
"thermal_cooling");
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index d5c1bbfbe79..73338d231db 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2562,7 +2562,8 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
const struct firmware *firmware;
struct device *device;
struct fw_header *fw_header;
- u32 *fw_data, fw_size;
+ const __le32 *fw_data;
+ u32 fw_size;
u32 __iomem *load_addr;
char buf[48];
int err = -ENODEV;
@@ -2582,7 +2583,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e)
return err;
}
- fw_data = (u32 *) firmware->data;
+ fw_data = (__le32 *) firmware->data;
fw_size = firmware->size / sizeof(u32);
fw_header = (struct fw_header *) firmware->data;
load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
@@ -3199,6 +3200,14 @@ static const struct fore200e_bus fore200e_bus[] = {
{}
};
-#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
+#ifdef CONFIG_PCI
+#ifdef __LITTLE_ENDIAN__
+MODULE_FIRMWARE("pca200e.bin");
+#else
+MODULE_FIRMWARE("pca200e_ecd.bin2");
+#endif
+#endif /* CONFIG_PCI */
+#ifdef CONFIG_SBUS
+MODULE_FIRMWARE("sba200e_ecd.bin2");
#endif
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c
index 683509f013a..eacb175f6bd 100644
--- a/drivers/auxdisplay/cfag12864b.c
+++ b/drivers/auxdisplay/cfag12864b.c
@@ -336,16 +336,9 @@ static int __init cfag12864b_init(void)
"ks0108 is not initialized\n");
goto none;
}
+ BUILD_BUG_ON(PAGE_SIZE < CFAG12864B_SIZE);
- if (PAGE_SIZE < CFAG12864B_SIZE) {
- printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
- "page size (%i) < cfag12864b size (%i)\n",
- (unsigned int)PAGE_SIZE, CFAG12864B_SIZE);
- ret = -ENOMEM;
- goto none;
- }
-
- cfag12864b_buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+ cfag12864b_buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
if (cfag12864b_buffer == NULL) {
printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
"can't get a free page\n");
@@ -367,8 +360,6 @@ static int __init cfag12864b_init(void)
if (cfag12864b_workqueue == NULL)
goto cachealloced;
- memset(cfag12864b_buffer, 0, CFAG12864B_SIZE);
-
cfag12864b_clear();
cfag12864b_on();
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d47482fa1d2..6318f6b5736 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -27,8 +27,9 @@ config PREVENT_FIRMWARE_BUILD
If unsure say Y here.
config FW_LOADER
- tristate "Userspace firmware loading support"
+ tristate "Userspace firmware loading support" if EMBEDDED
depends on HOTPLUG
+ default y
---help---
This option is provided for the case where no in-kernel-tree modules
require userspace firmware loading support, but a module built outside
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 2c9ae43e221..31dc0cd84af 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -36,6 +36,33 @@ struct driver_private {
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
+
+/**
+ * struct class_private - structure to hold the private to the driver core portions of the class structure.
+ *
+ * @class_subsys - the struct kset that defines this class. This is the main kobject
+ * @class_devices - list of devices associated with this class
+ * @class_interfaces - list of class_interfaces associated with this class
+ * @class_dirs - "glue" directory for virtual devices associated with this class
+ * @class_mutex - mutex to protect the children, devices, and interfaces lists.
+ * @class - pointer back to the struct class that this structure is associated
+ * with.
+ *
+ * This structure is the one that is the actual kobject allowing struct
+ * class to be statically allocated safely. Nothing outside of the driver
+ * core should ever touch these fields.
+ */
+struct class_private {
+ struct kset class_subsys;
+ struct list_head class_devices;
+ struct list_head class_interfaces;
+ struct kset class_dirs;
+ struct mutex class_mutex;
+ struct class *class;
+};
+#define to_class(obj) \
+ container_of(obj, struct class_private, class_subsys.kobj)
+
/* initialisation functions */
extern int devices_init(void);
extern int buses_init(void);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index e085af0ff94..839d27cecb3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -18,20 +18,20 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/genhd.h>
+#include <linux/mutex.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
-#define to_class(obj) container_of(obj, struct class, subsys.kobj)
static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct class_attribute *class_attr = to_class_attr(attr);
- struct class *dc = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
ssize_t ret = -EIO;
if (class_attr->show)
- ret = class_attr->show(dc, buf);
+ ret = class_attr->show(cp->class, buf);
return ret;
}
@@ -39,17 +39,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
struct class_attribute *class_attr = to_class_attr(attr);
- struct class *dc = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
ssize_t ret = -EIO;
if (class_attr->store)
- ret = class_attr->store(dc, buf, count);
+ ret = class_attr->store(cp->class, buf, count);
return ret;
}
static void class_release(struct kobject *kobj)
{
- struct class *class = to_class(kobj);
+ struct class_private *cp = to_class(kobj);
+ struct class *class = cp->class;
pr_debug("class '%s': release.\n", class->name);
@@ -70,7 +71,7 @@ static struct kobj_type class_ktype = {
.release = class_release,
};
-/* Hotplug events for classes go to the class_obj subsys */
+/* Hotplug events for classes go to the class class_subsys */
static struct kset *class_kset;
@@ -78,7 +79,8 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
{
int error;
if (cls)
- error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
+ error = sysfs_create_file(&cls->p->class_subsys.kobj,
+ &attr->attr);
else
error = -EINVAL;
return error;
@@ -87,21 +89,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr)
void class_remove_file(struct class *cls, const struct class_attribute *attr)
{
if (cls)
- sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
+ sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr);
}
static struct class *class_get(struct class *cls)
{
if (cls)
- return container_of(kset_get(&cls->subsys),
- struct class, subsys);
- return NULL;
+ kset_get(&cls->p->class_subsys);
+ return cls;
}
static void class_put(struct class *cls)
{
if (cls)
- kset_put(&cls->subsys);
+ kset_put(&cls->p->class_subsys);
}
static int add_class_attrs(struct class *cls)
@@ -134,42 +135,57 @@ static void remove_class_attrs(struct class *cls)
}
}
-int class_register(struct class *cls)
+int __class_register(struct class *cls, struct lock_class_key *key)
{
+ struct class_private *cp;
int error;
pr_debug("device class '%s': registering\n", cls->name);
- INIT_LIST_HEAD(&cls->devices);
- INIT_LIST_HEAD(&cls->interfaces);
- kset_init(&cls->class_dirs);
- init_MUTEX(&cls->sem);
- error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
- if (error)
+ cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+ if (!cp)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&cp->class_devices);
+ INIT_LIST_HEAD(&cp->class_interfaces);
+ kset_init(&cp->class_dirs);
+ __mutex_init(&cp->class_mutex, "struct class mutex", key);
+ error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
+ if (error) {
+ kfree(cp);
return error;
+ }
+
+ /* set the default /sys/dev directory for devices of this class */
+ if (!cls->dev_kobj)
+ cls->dev_kobj = sysfs_dev_char_kobj;
#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
/* let the block class directory show up in the root of sysfs */
if (cls != &block_class)
- cls->subsys.kobj.kset = class_kset;
+ cp->class_subsys.kobj.kset = class_kset;
#else
- cls->subsys.kobj.kset = class_kset;
+ cp->class_subsys.kobj.kset = class_kset;
#endif
- cls->subsys.kobj.ktype = &class_ktype;
+ cp->class_subsys.kobj.ktype = &class_ktype;
+ cp->class = cls;
+ cls->p = cp;
- error = kset_register(&cls->subsys);
- if (!error) {
- error = add_class_attrs(class_get(cls));
- class_put(cls);
+ error = kset_register(&cp->class_subsys);
+ if (error) {
+ kfree(cp);
+ return error;
}
+ error = add_class_attrs(class_get(cls));
+ class_put(cls);
return error;
}
+EXPORT_SYMBOL_GPL(__class_register);
void class_unregister(struct class *cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
remove_class_attrs(cls);
- kset_unregister(&cls->subsys);
+ kset_unregister(&cls->p->class_subsys);
}
static void class_create_release(struct class *cls)
@@ -189,7 +205,8 @@ static void class_create_release(struct class *cls)
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
-struct class *class_create(struct module *owner, const char *name)
+struct class *__class_create(struct module *owner, const char *name,
+ struct lock_class_key *key)
{
struct class *cls;
int retval;
@@ -204,7 +221,7 @@ struct class *class_create(struct module *owner, const char *name)
cls->owner = owner;
cls->class_release = class_create_release;
- retval = class_register(cls);
+ retval = __class_register(cls, key);
if (retval)
goto error;
@@ -214,6 +231,7 @@ error:
kfree(cls);
return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(__class_create);
/**
* class_destroy - destroys a struct class structure
@@ -252,39 +270,44 @@ char *make_class_name(const char *name, struct kobject *kobj)
/**
* class_for_each_device - device iterator
* @class: the class we're iterating
+ * @start: the device to start with in the list, if any.
* @data: data for the callback
* @fn: function to be called for each device
*
* Iterate over @class's list of devices, and call @fn for each,
- * passing it @data.
+ * passing it @data. If @start is set, the list iteration will start
+ * there, otherwise if it is NULL, the iteration starts at the
+ * beginning of the list.
*
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
- * Note, we hold class->sem in this function, so it can not be
+ * Note, we hold class->class_mutex in this function, so it can not be
* re-acquired in @fn, otherwise it will self-deadlocking. For
* example, calls to add or remove class members would be verboten.
*/
-int class_for_each_device(struct class *class, void *data,
- int (*fn)(struct device *, void *))
+int class_for_each_device(struct class *class, struct device *start,
+ void *data, int (*fn)(struct device *, void *))
{
struct device *dev;
int error = 0;
if (!class)
return -EINVAL;
- down(&class->sem);
- list_for_each_entry(dev, &class->devices, node) {
+ mutex_lock(&class->p->class_mutex);
+ list_for_each_entry(dev, &class->p->class_devices, node) {
+ if (start) {
+ if (start == dev)
+ start = NULL;
+ continue;
+ }
dev = get_device(dev);
- if (dev) {
- error = fn(dev, data);
- put_device(dev);
- } else
- error = -ENODEV;
+ error = fn(dev, data);
+ put_device(dev);
if (error)
break;
}
- up(&class->sem);
+ mutex_unlock(&class->p->class_mutex);
return error;
}
@@ -293,6 +316,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
/**
* class_find_device - device iterator for locating a particular device
* @class: the class we're iterating
+ * @start: Device to begin with
* @data: data for the match function
* @match: function to check device
*
@@ -306,12 +330,13 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
*
* Note, you will need to drop the reference with put_device() after use.
*
- * We hold class->sem in this function, so it can not be
+ * We hold class->class_mutex in this function, so it can not be
* re-acquired in @match, otherwise it will self-deadlocking. For
* example, calls to add or remove class members would be verboten.
*/
-struct device *class_find_device(struct class *class, void *data,
- int (*match)(struct device *, void *))
+struct device *class_find_device(struct class *class, struct device *start,
+ void *data,
+ int (*match)(struct device *, void *))
{
struct device *dev;
int found = 0;
@@ -319,19 +344,21 @@ struct device *class_find_device(struct class *class, void *data,
if (!class)
return NULL;
- down(&class->sem);
- list_for_each_entry(dev, &class->devices, node) {
+ mutex_lock(&class->p->class_mutex);
+ list_for_each_entry(dev, &class->p->class_devices, node) {
+ if (start) {
+ if (start == dev)
+ start = NULL;
+ continue;
+ }
dev = get_device(dev);
- if (dev) {
- if (match(dev, data)) {
- found = 1;
- break;
- } else
- put_device(dev);
- } else
+ if (match(dev, data)) {
+ found = 1;
break;
+ } else
+ put_device(dev);
}
- up(&class->sem);
+ mutex_unlock(&class->p->class_mutex);
return found ? dev : NULL;
}
@@ -349,13 +376,13 @@ int class_interface_register(struct class_interface *class_intf)
if (!parent)
return -EINVAL;
- down(&parent->sem);
- list_add_tail(&class_intf->node, &parent->interfaces);
+ mutex_lock(&parent->p->class_mutex);
+ list_add_tail(&class_intf->node, &parent->p->class_interfaces);
if (class_intf->add_dev) {
- list_for_each_entry(dev, &parent->devices, node)
+ list_for_each_entry(dev, &parent->p->class_devices, node)
class_intf->add_dev(dev, class_intf);
}
- up(&parent->sem);
+ mutex_unlock(&parent->p->class_mutex);
return 0;
}
@@ -368,13 +395,13 @@ void class_interface_unregister(struct class_interface *class_intf)
if (!parent)
return;
- down(&parent->sem);
+ mutex_lock(&parent->p->class_mutex);
list_del_init(&class_intf->node);
if (class_intf->remove_dev) {
- list_for_each_entry(dev, &parent->devices, node)
+ list_for_each_entry(dev, &parent->p->class_devices, node)
class_intf->remove_dev(dev, class_intf);
}
- up(&parent->sem);
+ mutex_unlock(&parent->p->class_mutex);
class_put(parent);
}
@@ -389,9 +416,7 @@ int __init classes_init(void)
EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
-EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
-EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy);
EXPORT_SYMBOL_GPL(class_interface_register);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index ee0a51a3a41..7d5c63c81a5 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -21,12 +21,16 @@
#include <linux/genhd.h>
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
+#include <linux/mutex.h>
#include "base.h"
#include "power/power.h"
int (*platform_notify)(struct device *dev) = NULL;
int (*platform_notify_remove)(struct device *dev) = NULL;
+static struct kobject *dev_kobj;
+struct kobject *sysfs_dev_char_kobj;
+struct kobject *sysfs_dev_block_kobj;
#ifdef CONFIG_BLOCK
static inline int device_is_not_partition(struct device *dev)
@@ -548,7 +552,7 @@ static struct kobject *get_device_parent(struct device *dev,
{
/* class devices without a parent live in /sys/class/<classname>/ */
if (dev->class && (!parent || parent->class != dev->class))
- return &dev->class->subsys.kobj;
+ return &dev->class->p->class_subsys.kobj;
/* all other devices keep their parent */
else if (parent)
return &parent->kobj;
@@ -594,13 +598,13 @@ static struct kobject *get_device_parent(struct device *dev,
parent_kobj = &parent->kobj;
/* find our class-directory at the parent and reference it */
- spin_lock(&dev->class->class_dirs.list_lock);
- list_for_each_entry(k, &dev->class->class_dirs.list, entry)
+ spin_lock(&dev->class->p->class_dirs.list_lock);
+ list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
if (k->parent == parent_kobj) {
kobj = kobject_get(k);
break;
}
- spin_unlock(&dev->class->class_dirs.list_lock);
+ spin_unlock(&dev->class->p->class_dirs.list_lock);
if (kobj)
return kobj;
@@ -608,7 +612,7 @@ static struct kobject *get_device_parent(struct device *dev,
k = kobject_create();
if (!k)
return NULL;
- k->kset = &dev->class->class_dirs;
+ k->kset = &dev->class->p->class_dirs;
retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
if (retval < 0) {
kobject_put(k);
@@ -627,7 +631,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
{
/* see if we live in a "glue" directory */
if (!glue_dir || !dev->class ||
- glue_dir->kset != &dev->class->class_dirs)
+ glue_dir->kset != &dev->class->p->class_dirs)
return;
kobject_put(glue_dir);
@@ -654,17 +658,18 @@ static int device_add_class_symlinks(struct device *dev)
if (!dev->class)
return 0;
- error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
+ error = sysfs_create_link(&dev->kobj,
+ &dev->class->p->class_subsys.kobj,
"subsystem");
if (error)
goto out;
#ifdef CONFIG_SYSFS_DEPRECATED
/* stacked class devices need a symlink in the class directory */
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev)) {
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out_subsys;
}
@@ -701,13 +706,14 @@ out_device:
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
out_busid:
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ dev->bus_id);
#else
/* link in the class directory pointing to the device */
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out_subsys;
@@ -720,7 +726,7 @@ out_busid:
return 0;
out_busid:
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
#endif
out_subsys:
@@ -746,14 +752,15 @@ static void device_remove_class_symlinks(struct device *dev)
sysfs_remove_link(&dev->kobj, "device");
}
- if (dev->kobj.parent != &dev->class->subsys.kobj &&
+ if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ dev->bus_id);
#else
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
- sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
#endif
sysfs_remove_link(&dev->kobj, "subsystem");
@@ -776,6 +783,54 @@ int dev_set_name(struct device *dev, const char *fmt, ...)
EXPORT_SYMBOL_GPL(dev_set_name);
/**
+ * device_to_dev_kobj - select a /sys/dev/ directory for the device
+ * @dev: device
+ *
+ * By default we select char/ for new entries. Setting class->dev_obj
+ * to NULL prevents an entry from being created. class->dev_kobj must
+ * be set (or cleared) before any devices are registered to the class
+ * otherwise device_create_sys_dev_entry() and
+ * device_remove_sys_dev_entry() will disagree about the the presence
+ * of the link.
+ */
+static struct kobject *device_to_dev_kobj(struct device *dev)
+{
+ struct kobject *kobj;
+
+ if (dev->class)
+ kobj = dev->class->dev_kobj;
+ else
+ kobj = sysfs_dev_char_kobj;
+
+ return kobj;
+}
+
+static int device_create_sys_dev_entry(struct device *dev)
+{
+ struct kobject *kobj = device_to_dev_kobj(dev);
+ int error = 0;
+ char devt_str[15];
+
+ if (kobj) {
+ format_dev_t(devt_str, dev->devt);
+ error = sysfs_create_link(kobj, &dev->kobj, devt_str);
+ }
+
+ return error;
+}
+
+static void device_remove_sys_dev_entry(struct device *dev)
+{
+ struct kobject *kobj = device_to_dev_kobj(dev);
+ char devt_str[15];
+
+ if (kobj) {
+ format_dev_t(devt_str, dev->devt);
+ sysfs_remove_link(kobj, devt_str);
+ }
+}
+
+/**
* device_add - add device to device hierarchy.
* @dev: device.
*
@@ -829,6 +884,10 @@ int device_add(struct device *dev)
error = device_create_file(dev, &devt_attr);
if (error)
goto ueventattrError;
+
+ error = device_create_sys_dev_entry(dev);
+ if (error)
+ goto devtattrError;
}
error = device_add_class_symlinks(dev);
@@ -849,15 +908,16 @@ int device_add(struct device *dev)
klist_add_tail(&dev->knode_parent, &parent->klist_children);
if (dev->class) {
- down(&dev->class->sem);
+ mutex_lock(&dev->class->p->class_mutex);
/* tie the class to the device */
- list_add_tail(&dev->node, &dev->class->devices);
+ list_add_tail(&dev->node, &dev->class->p->class_devices);
/* notify any interfaces that the device is here */
- list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ list_for_each_entry(class_intf,
+ &dev->class->p->class_interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
- up(&dev->class->sem);
+ mutex_unlock(&dev->class->p->class_mutex);
}
Done:
put_device(dev);
@@ -873,6 +933,9 @@ int device_add(struct device *dev)
device_remove_class_symlinks(dev);
SymlinkError:
if (MAJOR(dev->devt))
+ device_remove_sys_dev_entry(dev);
+ devtattrError:
+ if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr);
ueventattrError:
device_remove_file(dev, &uevent_attr);
@@ -948,19 +1011,22 @@ void device_del(struct device *dev)
device_pm_remove(dev);
if (parent)
klist_del(&dev->knode_parent);
- if (MAJOR(dev->devt))
+ if (MAJOR(dev->devt)) {
+ device_remove_sys_dev_entry(dev);
device_remove_file(dev, &devt_attr);
+ }
if (dev->class) {
device_remove_class_symlinks(dev);
- down(&dev->class->sem);
+ mutex_lock(&dev->class->p->class_mutex);
/* notify any interfaces that the device is now gone */
- list_for_each_entry(class_intf, &dev->class->interfaces, node)
+ list_for_each_entry(class_intf,
+ &dev->class->p->class_interfaces, node)
if (class_intf->remove_dev)
class_intf->remove_dev(dev, class_intf);
/* remove the device from the class list */
list_del_init(&dev->node);
- up(&dev->class->sem);
+ mutex_unlock(&dev->class->p->class_mutex);
}
device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
@@ -1074,7 +1140,25 @@ int __init devices_init(void)
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
if (!devices_kset)
return -ENOMEM;
+ dev_kobj = kobject_create_and_add("dev", NULL);
+ if (!dev_kobj)
+ goto dev_kobj_err;
+ sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
+ if (!sysfs_dev_block_kobj)
+ goto block_kobj_err;
+ sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
+ if (!sysfs_dev_char_kobj)
+ goto char_kobj_err;
+
return 0;
+
+ char_kobj_err:
+ kobject_put(sysfs_dev_block_kobj);
+ block_kobj_err:
+ kobject_put(dev_kobj);
+ dev_kobj_err:
+ kset_unregister(devices_kset);
+ return -ENOMEM;
}
EXPORT_SYMBOL_GPL(device_for_each_child);
@@ -1158,48 +1242,11 @@ error:
EXPORT_SYMBOL_GPL(device_create_vargs);
/**
- * device_create_drvdata - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- *
- * This function can be used by char device classes. A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_drvdata(struct class *class,
- struct device *parent,
- dev_t devt,
- void *drvdata,
- const char *fmt, ...)
-{
- va_list vargs;
- struct device *dev;
-
- va_start(vargs, fmt);
- dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
- va_end(vargs);
- return dev;
-}
-EXPORT_SYMBOL_GPL(device_create_drvdata);
-
-/**
* device_create - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
* @fmt: string for the device's name
*
* This function can be used by char device classes. A struct device
@@ -1217,13 +1264,13 @@ EXPORT_SYMBOL_GPL(device_create_drvdata);
* been created with a call to class_create().
*/
struct device *device_create(struct class *class, struct device *parent,
- dev_t devt, const char *fmt, ...)
+ dev_t devt, void *drvdata, const char *fmt, ...)
{
va_list vargs;
struct device *dev;
va_start(vargs, fmt);
- dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
+ dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
va_end(vargs);
return dev;
}
@@ -1248,7 +1295,7 @@ void device_destroy(struct class *class, dev_t devt)
{
struct device *dev;
- dev = class_find_device(class, &devt, __match_devt);
+ dev = class_find_device(class, NULL, &devt, __match_devt);
if (dev) {
put_device(dev);
device_unregister(dev);
@@ -1298,8 +1345,9 @@ int device_rename(struct device *dev, char *new_name)
if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) {
- error = sysfs_create_link(&dev->parent->kobj,
- &dev->kobj, new_class_name);
+ error = sysfs_create_link_nowarn(&dev->parent->kobj,
+ &dev->kobj,
+ new_class_name);
if (error)
goto out;
sysfs_remove_link(&dev->parent->kobj, old_class_name);
@@ -1307,11 +1355,12 @@ int device_rename(struct device *dev, char *new_name)
}
#else
if (dev->class) {
- error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- dev->bus_id);
+ error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, dev->bus_id);
if (error)
goto out;
- sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+ old_device_name);
}
#endif
@@ -1447,4 +1496,7 @@ void device_shutdown(void)
dev->driver->shutdown(dev);
}
}
+ kobject_put(sysfs_dev_char_kobj);
+ kobject_put(sysfs_dev_block_kobj);
+ kobject_put(dev_kobj);
}
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index e38dfed41d8..64f5d54f7ed 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -21,15 +21,16 @@ EXPORT_SYMBOL(cpu_sysdev_class);
static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t show_online(struct sys_device *dev, char *buf)
+static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
}
-static ssize_t __ref store_online(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
+ const char *buf, size_t count)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
ssize_t ret;
@@ -80,7 +81,8 @@ static inline void register_cpu_control(struct cpu *cpu)
#ifdef CONFIG_KEXEC
#include <linux/kexec.h>
-static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
+ char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
ssize_t rc;
@@ -119,14 +121,14 @@ static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
{ \
return print_cpus_map(buf, &cpu_##type##_map); \
} \
-struct sysdev_class_attribute attr_##type##_map = \
+static struct sysdev_class_attribute attr_##type##_map = \
_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
print_cpus_func(online);
print_cpus_func(possible);
print_cpus_func(present);
-struct sysdev_class_attribute *cpu_state_attr[] = {
+static struct sysdev_class_attribute *cpu_state_attr[] = {
&attr_online_map,
&attr_possible_map,
&attr_present_map,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 937e8258981..855ed1a9f97 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -92,7 +92,8 @@ unregister_memory(struct memory_block *memory, struct mem_section *section)
* uses.
*/
-static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
+static ssize_t show_mem_phys_index(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -100,9 +101,25 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
}
/*
+ * Show whether the section of memory is likely to be hot-removable
+ */
+static ssize_t show_mem_removable(struct sys_device *dev, char *buf)
+{
+ unsigned long start_pfn;
+ int ret;
+ struct memory_block *mem =
+ container_of(dev, struct memory_block, sysdev);
+
+ start_pfn = section_nr_to_pfn(mem->phys_index);
+ ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+ return sprintf(buf, "%d\n", ret);
+}
+
+/*
* online, offline, going offline, etc.
*/
-static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+static ssize_t show_mem_state(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -217,7 +234,8 @@ out:
}
static ssize_t
-store_mem_state(struct sys_device *dev, const char *buf, size_t count)
+store_mem_state(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf, size_t count)
{
struct memory_block *mem;
unsigned int phys_section_nr;
@@ -248,7 +266,8 @@ out:
* s.t. if I offline all of these sections I can then
* remove the physical device?
*/
-static ssize_t show_phys_device(struct sys_device *dev, char *buf)
+static ssize_t show_phys_device(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
struct memory_block *mem =
container_of(dev, struct memory_block, sysdev);
@@ -258,6 +277,7 @@ static ssize_t show_phys_device(struct sys_device *dev, char *buf)
static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
+static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
#define mem_create_simple_file(mem, attr_name) \
sysdev_create_file(&mem->sysdev, &attr_##attr_name)
@@ -346,6 +366,8 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
ret = mem_create_simple_file(mem, state);
if (!ret)
ret = mem_create_simple_file(mem, phys_device);
+ if (!ret)
+ ret = mem_create_simple_file(mem, removable);
return ret;
}
@@ -390,6 +412,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
mem_remove_simple_file(mem, phys_index);
mem_remove_simple_file(mem, state);
mem_remove_simple_file(mem, phys_device);
+ mem_remove_simple_file(mem, removable);
unregister_memory(mem, section);
return 0;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 0f867a08333..5116b78c632 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -36,11 +36,13 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
return len;
}
-static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpumask(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
return node_read_cpumap(dev, 0, buf);
}
-static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpulist(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
return node_read_cpumap(dev, 1, buf);
}
@@ -49,7 +51,8 @@ static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
#define K(x) ((x) << (PAGE_SHIFT - 10))
-static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+static ssize_t node_read_meminfo(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
int n;
int nid = dev->id;
@@ -112,7 +115,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
#undef K
static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
-static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
+static ssize_t node_read_numastat(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
return sprintf(buf,
"numa_hit %lu\n"
@@ -130,7 +134,8 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
}
static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
-static ssize_t node_read_distance(struct sys_device * dev, char * buf)
+static ssize_t node_read_distance(struct sys_device * dev,
+ struct sysdev_attribute *attr, char * buf)
{
int nid = dev->id;
int len = 0;
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 9b1b20b59e0..2aa6e8fc4de 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -194,7 +194,7 @@ static int show_dev_hash(unsigned int value)
struct device * dev = to_device(entry);
unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
if (hash == value) {
- printk(" hash matches device %s\n", dev->bus_id);
+ dev_info(dev, "hash matches\n");
match++;
}
entry = entry->prev;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 358bb0be3c0..40fc14f0354 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -36,7 +36,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->show)
- return sysdev_attr->show(sysdev, buffer);
+ return sysdev_attr->show(sysdev, sysdev_attr, buffer);
return -EIO;
}
@@ -49,7 +49,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr,
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
if (sysdev_attr->store)
- return sysdev_attr->store(sysdev, buffer, count);
+ return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
return -EIO;
}
@@ -130,8 +130,8 @@ static struct kset *system_kset;
int sysdev_class_register(struct sysdev_class * cls)
{
- pr_debug("Registering sysdev class '%s'\n",
- kobject_name(&cls->kset.kobj));
+ pr_debug("Registering sysdev class '%s'\n", cls->name);
+
INIT_LIST_HEAD(&cls->drivers);
memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
cls->kset.kobj.parent = &system_kset->kobj;
@@ -241,7 +241,8 @@ int sysdev_register(struct sys_device * sysdev)
if (!cls)
return -EINVAL;
- pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
+ pr_debug("Registering sys device of class '%s'\n",
+ kobject_name(&cls->kset.kobj));
/* initialize the kobject to 0, in case it had previously been used */
memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
@@ -257,6 +258,9 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
+ pr_debug("Registering sys device '%s'\n",
+ kobject_name(&sysdev->kobj));
+
mutex_lock(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
@@ -269,6 +273,7 @@ int sysdev_register(struct sys_device * sysdev)
}
mutex_unlock(&sysdev_drivers_lock);
}
+
kobject_uevent(&sysdev->kobj, KOBJ_ADD);
return error;
}
@@ -474,3 +479,52 @@ int __init system_bus_init(void)
EXPORT_SYMBOL_GPL(sysdev_register);
EXPORT_SYMBOL_GPL(sysdev_unregister);
+
+#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
+
+ssize_t sysdev_store_ulong(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ char *end;
+ unsigned long new = simple_strtoul(buf, &end, 0);
+ if (end == buf)
+ return -EINVAL;
+ *(unsigned long *)(ea->var) = new;
+ return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_ulong);
+
+ssize_t sysdev_show_ulong(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_ulong);
+
+ssize_t sysdev_store_int(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ char *end;
+ long new = simple_strtol(buf, &end, 0);
+ if (end == buf || new > INT_MAX || new < INT_MIN)
+ return -EINVAL;
+ *(int *)(ea->var) = new;
+ return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_int);
+
+ssize_t sysdev_show_int(struct sys_device *sysdev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+ return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_int);
+
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 3f6d9b0a6ab..199cd97e32e 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -34,7 +34,8 @@
static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
#define define_id_show_func(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
return sprintf(buf, "%d\n", topology_##name(cpu)); \
@@ -59,14 +60,17 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
#ifdef arch_provides_topology_pointers
#define define_siblings_show_map(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
return show_cpumap(0, &(topology_##name(cpu)), buf); \
}
#define define_siblings_show_list(name) \
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
{ \
unsigned int cpu = dev->id; \
return show_cpumap(1, &(topology_##name(cpu)), buf); \
@@ -74,7 +78,8 @@ static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
#else
#define define_siblings_show_map(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_##name(struct sys_device *dev, \
+ struct sysdev_attribute *attr, char *buf) \
{ \
unsigned int cpu = dev->id; \
cpumask_t mask = topology_##name(cpu); \
@@ -82,7 +87,9 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \
}
#define define_siblings_show_list(name) \
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev, \
+ struct sysdev_attribute *attr, \
+ char *buf) \
{ \
unsigned int cpu = dev->id; \
cpumask_t mask = topology_##name(cpu); \
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index d1de68a3192..c04440cd6a3 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -277,8 +277,9 @@ aoechr_init(void)
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- device_create(aoe_class, NULL,
- MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
+ device_create_drvdata(aoe_class, NULL,
+ MKDEV(AOE_MAJOR, chardevs[i].minor),
+ NULL, chardevs[i].name);
return 0;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9d92636350e..d731ca42f80 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -686,8 +686,9 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present)
- device_create(pg_class, NULL, MKDEV(major, unit),
- "pg%u", unit);
+ device_create_drvdata(pg_class, NULL,
+ MKDEV(major, unit), NULL,
+ "pg%u", unit);
}
err = 0;
goto out;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5c74c3574a5..673b8b2fd33 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -979,10 +979,12 @@ static int __init pt_init(void)
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- device_create(pt_class, NULL, MKDEV(major, unit),
- "pt%d", unit);
- device_create(pt_class, NULL, MKDEV(major, unit + 128),
- "pt%dn", unit);
+ device_create_drvdata(pt_class, NULL,
+ MKDEV(major, unit), NULL,
+ "pt%d", unit);
+ device_create_drvdata(pt_class, NULL,
+ MKDEV(major, unit + 128), NULL,
+ "pt%dn", unit);
}
goto out;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 45bee918c46..158eed4d516 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -303,7 +303,9 @@ static struct kobj_type kobj_pkt_type_wqueue = {
static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
{
if (class_pktcdvd) {
- pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name);
+ pd->dev = device_create_drvdata(class_pktcdvd, NULL,
+ pd->pkt_dev, NULL,
+ "%s", pd->name);
if (IS_ERR(pd->dev))
pd->dev = NULL;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 650e6b44ce6..67b07576f8b 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -300,16 +300,6 @@ config SPECIALIX
and compile this driver as kernel loadable module which will be
called specialix.
-config SPECIALIX_RTSCTS
- bool "Specialix DTR/RTS pin is RTS"
- depends on SPECIALIX
- help
- The Specialix IO8+ card can only support either RTS or DTR. If you
- say N here, the driver will use the pin as "DTR" when the tty is in
- software handshake mode. If you say Y here or hardware handshake is
- on, it will always be RTS. Read the file
- <file:Documentation/specialix.txt> for more information.
-
config SX
tristate "Specialix SX (and SI) card support"
depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
@@ -867,13 +857,6 @@ config DS1302
endif # RTC_LIB
-config COBALT_LCD
- bool "Support for Cobalt LCD"
- depends on MIPS_COBALT
- help
- This option enables support for the LCD display and buttons found
- on Cobalt systems through a misc device.
-
config DTLK
tristate "Double Talk PC internal speech card support"
depends on ISA
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 0e0d12a0646..4b6e736cfa0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -7,7 +7,7 @@
#
FONTMAPFILE = cp437.uni
-obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
+obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
@@ -88,7 +88,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random/
-obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 37457e5a4f2..3530ff417a5 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
/*
* rs_break() --- routine which turns the break handling on or off
*/
-static void rs_break(struct tty_struct *tty, int break_state)
+static int rs_break(struct tty_struct *tty, int break_state)
{
struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned long flags;
@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state)
custom.adkcon = AC_UARTBRK;
mb();
local_irq_restore(flags);
+ return 0;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e991dc85f2f..fe6d774fe2e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
/*
* cy_break() --- routine which turns the break handling on or off
*/
-static void cy_break(struct tty_struct *tty, int break_state)
+static int cy_break(struct tty_struct *tty, int break_state)
{
struct cyclades_port *info = tty->driver_data;
struct cyclades_card *card;
unsigned long flags;
+ int retval = 0;
if (serial_paranoia_check(info, tty->name, "cy_break"))
- return;
+ return -EINVAL;
card = info->card;
@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
}
}
} else {
- int retval;
-
if (break_state == -1) {
retval = cyz_issue_cmd(card,
info->line - card->first_line,
@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
}
}
spin_unlock_irqrestore(&card->card_lock, flags);
+ return retval;
} /* cy_break */
static int get_mon_info(struct cyclades_port *info,
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index b9a30c30e2b..33c466a4888 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -500,7 +500,8 @@ static int __init dsp56k_init_driver(void)
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
+ device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
+ NULL, "dsp56k");
printk(banner);
goto out;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index ac9995f6578..456e4ede049 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -184,9 +184,8 @@ static void pc_stop(struct tty_struct *);
static void pc_start(struct tty_struct *);
static void pc_throttle(struct tty_struct *tty);
static void pc_unthrottle(struct tty_struct *tty);
-static void digi_send_break(struct channel *ch, int msec);
+static int pc_send_break(struct tty_struct *tty, int msec);
static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-static void epca_setup(char *, int *);
static int pc_write(struct tty_struct *, const unsigned char *, int);
static int pc_init(void);
@@ -1040,6 +1039,7 @@ static const struct tty_operations pc_ops = {
.throttle = pc_throttle,
.unthrottle = pc_unthrottle,
.hangup = pc_hangup,
+ .break_ctl = pc_send_break
};
static int info_open(struct tty_struct *tty, struct file *filp)
@@ -1132,7 +1132,7 @@ static int __init pc_init(void)
pc_driver->init_termios.c_lflag = 0;
pc_driver->init_termios.c_ispeed = 9600;
pc_driver->init_termios.c_ospeed = 9600;
- pc_driver->flags = TTY_DRIVER_REAL_RAW;
+ pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(pc_driver, &pc_ops);
pc_info->owner = THIS_MODULE;
@@ -2177,7 +2177,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
digiflow_t dflow;
- int retval;
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
@@ -2189,37 +2188,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
bc = ch->brdchan;
else
return -EINVAL;
- /*
- * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
- * /usr/src/linux/drivers/char for a good example. In particular think
- * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
- */
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- /* Setup an event to indicate when the transmit
- buffer empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty, ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- if (!arg)
- digi_send_break(ch, HZ / 4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- /* Setup an event to indicate when the transmit buffer
- empties */
- spin_lock_irqsave(&epca_lock, flags);
- setup_empty_event(tty, ch);
- spin_unlock_irqrestore(&epca_lock, flags);
- tty_wait_until_sent(tty, 0);
- digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
- return 0;
case TIOCMODG:
mflag = pc_tiocmget(tty, file);
if (put_user(mflag, (unsigned long __user *)argp))
@@ -2505,10 +2474,14 @@ static void pc_unthrottle(struct tty_struct *tty)
}
}
-static void digi_send_break(struct channel *ch, int msec)
+static int pc_send_break(struct tty_struct *tty, int msec)
{
+ struct channel *ch = (struct channel *) tty->driver_data;
unsigned long flags;
+ if (msec == -1)
+ return -EOPNOTSUPP;
+
spin_lock_irqsave(&epca_lock, flags);
globalwinon(ch);
/*
@@ -2521,6 +2494,7 @@ static void digi_send_break(struct channel *ch, int msec)
fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
memoff(ch);
spin_unlock_irqrestore(&epca_lock, flags);
+ return 0;
}
/* Caller MUST hold the lock */
@@ -2538,7 +2512,8 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
memoff(ch);
}
-static void epca_setup(char *str, int *ints)
+#ifndef MODULE
+static void __init epca_setup(char *str, int *ints)
{
struct board_info board;
int index, loop, last;
@@ -2792,6 +2767,17 @@ static void epca_setup(char *str, int *ints)
num_cards++;
}
+static int __init epca_real_setup(char *str)
+{
+ int ints[11];
+
+ epca_setup(get_options(str, 11, ints), ints);
+ return 1;
+}
+
+__setup("digiepca", epca_real_setup);
+#endif
+
enum epic_board_types {
brd_xr = 0,
brd_xem,
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2eaf09f93e3..7f077c0097f 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
/*
* rs_break() --- routine which turns the break handling on or off
*/
-static void esp_break(struct tty_struct *tty, int break_state)
+static int esp_break(struct tty_struct *tty, int break_state)
{
struct esp_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "esp_break"))
- return;
+ return -EINVAL;
if (break_state == -1) {
spin_lock_irqsave(&info->lock, flags);
@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state)
serial_out(info, UART_ESI_CMD2, 0x00);
spin_unlock_irqrestore(&info->lock, flags);
}
+ return 0;
}
static int rs_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index efd0b4db7c8..8822eca58ff 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -59,6 +59,19 @@ config HW_RANDOM_GEODE
If unsure, say Y.
+config HW_RANDOM_N2RNG
+ tristate "Niagara2 Random Number Generator support"
+ depends on HW_RANDOM && SPARC64
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Niagara2 cpus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called n2-rng.
+
+ If unsure, say Y.
+
config HW_RANDOM_VIA
tristate "VIA HW Random Number Generator support"
depends on HW_RANDOM && X86_32
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b4940ddbb35..b6effb7522c 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -7,6 +7,8 @@ rng-core-y := core.o
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
+obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
+n2-rng-y := n2-drv.o n2-asm.o
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
diff --git a/drivers/char/hw_random/n2-asm.S b/drivers/char/hw_random/n2-asm.S
new file mode 100644
index 00000000000..9b6eb5cd59f
--- /dev/null
+++ b/drivers/char/hw_random/n2-asm.S
@@ -0,0 +1,79 @@
+/* n2-asm.S: Niagara2 RNG hypervisor call assembler.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/linkage.h>
+#include <asm/hypervisor.h>
+#include "n2rng.h"
+
+ .text
+
+ENTRY(sun4v_rng_get_diag_ctl)
+ mov HV_FAST_RNG_GET_DIAG_CTL, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ENDPROC(sun4v_rng_get_diag_ctl)
+
+ENTRY(sun4v_rng_ctl_read_v1)
+ mov %o1, %o3
+ mov %o2, %o4
+ mov HV_FAST_RNG_CTL_READ, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o3]
+ retl
+ stx %o2, [%o4]
+ENDPROC(sun4v_rng_ctl_read_v1)
+
+ENTRY(sun4v_rng_ctl_read_v2)
+ save %sp, -192, %sp
+ mov %i0, %o0
+ mov %i1, %o1
+ mov HV_FAST_RNG_CTL_READ, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%i2]
+ stx %o2, [%i3]
+ stx %o3, [%i4]
+ stx %o4, [%i5]
+ ret
+ restore %g0, %o0, %o0
+ENDPROC(sun4v_rng_ctl_read_v2)
+
+ENTRY(sun4v_rng_ctl_write_v1)
+ mov %o3, %o4
+ mov HV_FAST_RNG_CTL_WRITE, %o5
+ ta HV_FAST_TRAP
+ retl
+ stx %o1, [%o4]
+ENDPROC(sun4v_rng_ctl_write_v1)
+
+ENTRY(sun4v_rng_ctl_write_v2)
+ mov HV_FAST_RNG_CTL_WRITE, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ENDPROC(sun4v_rng_ctl_write_v2)
+
+ENTRY(sun4v_rng_data_read_diag_v1)
+ mov %o2, %o4
+ mov HV_FAST_RNG_DATA_READ_DIAG, %o5
+ ta HV_FAST_TRAP
+ retl
+ stx %o1, [%o4]
+ENDPROC(sun4v_rng_data_read_diag_v1)
+
+ENTRY(sun4v_rng_data_read_diag_v2)
+ mov %o3, %o4
+ mov HV_FAST_RNG_DATA_READ_DIAG, %o5
+ ta HV_FAST_TRAP
+ retl
+ stx %o1, [%o4]
+ENDPROC(sun4v_rng_data_read_diag_v2)
+
+ENTRY(sun4v_rng_data_read)
+ mov %o1, %o4
+ mov HV_FAST_RNG_DATA_READ, %o5
+ ta HV_FAST_TRAP
+ retl
+ stx %o1, [%o4]
+ENDPROC(sun4v_rng_data_read)
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
new file mode 100644
index 00000000000..5220f541df2
--- /dev/null
+++ b/drivers/char/hw_random/n2-drv.c
@@ -0,0 +1,771 @@
+/* n2-drv.c: Niagara-2 RNG driver.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/preempt.h>
+#include <linux/hw_random.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <asm/hypervisor.h>
+
+#include "n2rng.h"
+
+#define DRV_MODULE_NAME "n2rng"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "0.1"
+#define DRV_MODULE_RELDATE "May 15, 2008"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Niagara2 RNG driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* The Niagara2 RNG provides a 64-bit read-only random number
+ * register, plus a control register. Access to the RNG is
+ * virtualized through the hypervisor so that both guests and control
+ * nodes can access the device.
+ *
+ * The entropy source consists of raw entropy sources, each
+ * constructed from a voltage controlled oscillator whose phase is
+ * jittered by thermal noise sources.
+ *
+ * The oscillator in each of the three raw entropy sources run at
+ * different frequencies. Normally, all three generator outputs are
+ * gathered, xored together, and fed into a CRC circuit, the output of
+ * which is the 64-bit read-only register.
+ *
+ * Some time is necessary for all the necessary entropy to build up
+ * such that a full 64-bits of entropy are available in the register.
+ * In normal operating mode (RNG_CTL_LFSR is set), the chip implements
+ * an interlock which blocks register reads until sufficient entropy
+ * is available.
+ *
+ * A control register is provided for adjusting various aspects of RNG
+ * operation, and to enable diagnostic modes. Each of the three raw
+ * entropy sources has an enable bit (RNG_CTL_ES{1,2,3}). Also
+ * provided are fields for controlling the minimum time in cycles
+ * between read accesses to the register (RNG_CTL_WAIT, this controls
+ * the interlock described in the previous paragraph).
+ *
+ * The standard setting is to have the mode bit (RNG_CTL_LFSR) set,
+ * all three entropy sources enabled, and the interlock time set
+ * appropriately.
+ *
+ * The CRC polynomial used by the chip is:
+ *
+ * P(X) = x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + x46 +
+ * x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + x28 + x25 +
+ * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1
+ *
+ * The RNG_CTL_VCO value of each noise cell must be programmed
+ * seperately. This is why 4 control register values must be provided
+ * to the hypervisor. During a write, the hypervisor writes them all,
+ * one at a time, to the actual RNG_CTL register. The first three
+ * values are used to setup the desired RNG_CTL_VCO for each entropy
+ * source, for example:
+ *
+ * control 0: (1 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES1
+ * control 1: (2 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES2
+ * control 2: (3 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES3
+ *
+ * And then the fourth value sets the final chip state and enables
+ * desired.
+ */
+
+static int n2rng_hv_err_trans(unsigned long hv_err)
+{
+ switch (hv_err) {
+ case HV_EOK:
+ return 0;
+ case HV_EWOULDBLOCK:
+ return -EAGAIN;
+ case HV_ENOACCESS:
+ return -EPERM;
+ case HV_EIO:
+ return -EIO;
+ case HV_EBUSY:
+ return -EBUSY;
+ case HV_EBADALIGN:
+ case HV_ENORADDR:
+ return -EFAULT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static unsigned long n2rng_generic_read_control_v2(unsigned long ra,
+ unsigned long unit)
+{
+ unsigned long hv_err, state, ticks, watchdog_delta, watchdog_status;
+ int block = 0, busy = 0;
+
+ while (1) {
+ hv_err = sun4v_rng_ctl_read_v2(ra, unit, &state,
+ &ticks,
+ &watchdog_delta,
+ &watchdog_status);
+ if (hv_err == HV_EOK)
+ break;
+
+ if (hv_err == HV_EBUSY) {
+ if (++busy >= N2RNG_BUSY_LIMIT)
+ break;
+
+ udelay(1);
+ } else if (hv_err == HV_EWOULDBLOCK) {
+ if (++block >= N2RNG_BLOCK_LIMIT)
+ break;
+
+ __delay(ticks);
+ } else
+ break;
+ }
+
+ return hv_err;
+}
+
+/* In multi-socket situations, the hypervisor might need to
+ * queue up the RNG control register write if it's for a unit
+ * that is on a cpu socket other than the one we are executing on.
+ *
+ * We poll here waiting for a successful read of that control
+ * register to make sure the write has been actually performed.
+ */
+static unsigned long n2rng_control_settle_v2(struct n2rng *np, int unit)
+{
+ unsigned long ra = __pa(&np->scratch_control[0]);
+
+ return n2rng_generic_read_control_v2(ra, unit);
+}
+
+static unsigned long n2rng_write_ctl_one(struct n2rng *np, int unit,
+ unsigned long state,
+ unsigned long control_ra,
+ unsigned long watchdog_timeout,
+ unsigned long *ticks)
+{
+ unsigned long hv_err;
+
+ if (np->hvapi_major == 1) {
+ hv_err = sun4v_rng_ctl_write_v1(control_ra, state,
+ watchdog_timeout, ticks);
+ } else {
+ hv_err = sun4v_rng_ctl_write_v2(control_ra, state,
+ watchdog_timeout, unit);
+ if (hv_err == HV_EOK)
+ hv_err = n2rng_control_settle_v2(np, unit);
+ *ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
+ }
+
+ return hv_err;
+}
+
+static int n2rng_generic_read_data(unsigned long data_ra)
+{
+ unsigned long ticks, hv_err;
+ int block = 0, hcheck = 0;
+
+ while (1) {
+ hv_err = sun4v_rng_data_read(data_ra, &ticks);
+ if (hv_err == HV_EOK)
+ return 0;
+
+ if (hv_err == HV_EWOULDBLOCK) {
+ if (++block >= N2RNG_BLOCK_LIMIT)
+ return -EWOULDBLOCK;
+ __delay(ticks);
+ } else if (hv_err == HV_ENOACCESS) {
+ return -EPERM;
+ } else if (hv_err == HV_EIO) {
+ if (++hcheck >= N2RNG_HCHECK_LIMIT)
+ return -EIO;
+ udelay(10000);
+ } else
+ return -ENODEV;
+ }
+}
+
+static unsigned long n2rng_read_diag_data_one(struct n2rng *np,
+ unsigned long unit,
+ unsigned long data_ra,
+ unsigned long data_len,
+ unsigned long *ticks)
+{
+ unsigned long hv_err;
+
+ if (np->hvapi_major == 1) {
+ hv_err = sun4v_rng_data_read_diag_v1(data_ra, data_len, ticks);
+ } else {
+ hv_err = sun4v_rng_data_read_diag_v2(data_ra, data_len,
+ unit, ticks);
+ if (!*ticks)
+ *ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
+ }
+ return hv_err;
+}
+
+static int n2rng_generic_read_diag_data(struct n2rng *np,
+ unsigned long unit,
+ unsigned long data_ra,
+ unsigned long data_len)
+{
+ unsigned long ticks, hv_err;
+ int block = 0;
+
+ while (1) {
+ hv_err = n2rng_read_diag_data_one(np, unit,
+ data_ra, data_len,
+ &ticks);
+ if (hv_err == HV_EOK)
+ return 0;
+
+ if (hv_err == HV_EWOULDBLOCK) {
+ if (++block >= N2RNG_BLOCK_LIMIT)
+ return -EWOULDBLOCK;
+ __delay(ticks);
+ } else if (hv_err == HV_ENOACCESS) {
+ return -EPERM;
+ } else if (hv_err == HV_EIO) {
+ return -EIO;
+ } else
+ return -ENODEV;
+ }
+}
+
+
+static int n2rng_generic_write_control(struct n2rng *np,
+ unsigned long control_ra,
+ unsigned long unit,
+ unsigned long state)
+{
+ unsigned long hv_err, ticks;
+ int block = 0, busy = 0;
+
+ while (1) {
+ hv_err = n2rng_write_ctl_one(np, unit, state, control_ra,
+ np->wd_timeo, &ticks);
+ if (hv_err == HV_EOK)
+ return 0;
+
+ if (hv_err == HV_EWOULDBLOCK) {
+ if (++block >= N2RNG_BLOCK_LIMIT)
+ return -EWOULDBLOCK;
+ __delay(ticks);
+ } else if (hv_err == HV_EBUSY) {
+ if (++busy >= N2RNG_BUSY_LIMIT)
+ return -EBUSY;
+ udelay(1);
+ } else
+ return -ENODEV;
+ }
+}
+
+/* Just try to see if we can successfully access the control register
+ * of the RNG on the domain on which we are currently executing.
+ */
+static int n2rng_try_read_ctl(struct n2rng *np)
+{
+ unsigned long hv_err;
+ unsigned long x;
+
+ if (np->hvapi_major == 1) {
+ hv_err = sun4v_rng_get_diag_ctl();
+ } else {
+ /* We purposefully give invalid arguments, HV_NOACCESS
+ * is higher priority than the errors we'd get from
+ * these other cases, and that's the error we are
+ * truly interested in.
+ */
+ hv_err = sun4v_rng_ctl_read_v2(0UL, ~0UL, &x, &x, &x, &x);
+ switch (hv_err) {
+ case HV_EWOULDBLOCK:
+ case HV_ENOACCESS:
+ break;
+ default:
+ hv_err = HV_EOK;
+ break;
+ }
+ }
+
+ return n2rng_hv_err_trans(hv_err);
+}
+
+#define CONTROL_DEFAULT_BASE \
+ ((2 << RNG_CTL_ASEL_SHIFT) | \
+ (N2RNG_ACCUM_CYCLES_DEFAULT << RNG_CTL_WAIT_SHIFT) | \
+ RNG_CTL_LFSR)
+
+#define CONTROL_DEFAULT_0 \
+ (CONTROL_DEFAULT_BASE | \
+ (1 << RNG_CTL_VCO_SHIFT) | \
+ RNG_CTL_ES1)
+#define CONTROL_DEFAULT_1 \
+ (CONTROL_DEFAULT_BASE | \
+ (2 << RNG_CTL_VCO_SHIFT) | \
+ RNG_CTL_ES2)
+#define CONTROL_DEFAULT_2 \
+ (CONTROL_DEFAULT_BASE | \
+ (3 << RNG_CTL_VCO_SHIFT) | \
+ RNG_CTL_ES3)
+#define CONTROL_DEFAULT_3 \
+ (CONTROL_DEFAULT_BASE | \
+ RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3)
+
+static void n2rng_control_swstate_init(struct n2rng *np)
+{
+ int i;
+
+ np->flags |= N2RNG_FLAG_CONTROL;
+
+ np->health_check_sec = N2RNG_HEALTH_CHECK_SEC_DEFAULT;
+ np->accum_cycles = N2RNG_ACCUM_CYCLES_DEFAULT;
+ np->wd_timeo = N2RNG_WD_TIMEO_DEFAULT;
+
+ for (i = 0; i < np->num_units; i++) {
+ struct n2rng_unit *up = &np->units[i];
+
+ up->control[0] = CONTROL_DEFAULT_0;
+ up->control[1] = CONTROL_DEFAULT_1;
+ up->control[2] = CONTROL_DEFAULT_2;
+ up->control[3] = CONTROL_DEFAULT_3;
+ }
+
+ np->hv_state = HV_RNG_STATE_UNCONFIGURED;
+}
+
+static int n2rng_grab_diag_control(struct n2rng *np)
+{
+ int i, busy_count, err = -ENODEV;
+
+ busy_count = 0;
+ for (i = 0; i < 100; i++) {
+ err = n2rng_try_read_ctl(np);
+ if (err != -EAGAIN)
+ break;
+
+ if (++busy_count > 100) {
+ dev_err(&np->op->dev,
+ "Grab diag control timeout.\n");
+ return -ENODEV;
+ }
+
+ udelay(1);
+ }
+
+ return err;
+}
+
+static int n2rng_init_control(struct n2rng *np)
+{
+ int err = n2rng_grab_diag_control(np);
+
+ /* Not in the control domain, that's OK we are only a consumer
+ * of the RNG data, we don't setup and program it.
+ */
+ if (err == -EPERM)
+ return 0;
+ if (err)
+ return err;
+
+ n2rng_control_swstate_init(np);
+
+ return 0;
+}
+
+static int n2rng_data_read(struct hwrng *rng, u32 *data)
+{
+ struct n2rng *np = (struct n2rng *) rng->priv;
+ unsigned long ra = __pa(&np->test_data);
+ int len;
+
+ if (!(np->flags & N2RNG_FLAG_READY)) {
+ len = 0;
+ } else if (np->flags & N2RNG_FLAG_BUFFER_VALID) {
+ np->flags &= ~N2RNG_FLAG_BUFFER_VALID;
+ *data = np->buffer;
+ len = 4;
+ } else {
+ int err = n2rng_generic_read_data(ra);
+ if (!err) {
+ np->buffer = np->test_data >> 32;
+ *data = np->test_data & 0xffffffff;
+ len = 4;
+ } else {
+ dev_err(&np->op->dev, "RNG error, restesting\n");
+ np->flags &= ~N2RNG_FLAG_READY;
+ if (!(np->flags & N2RNG_FLAG_SHUTDOWN))
+ schedule_delayed_work(&np->work, 0);
+ len = 0;
+ }
+ }
+
+ return len;
+}
+
+/* On a guest node, just make sure we can read random data properly.
+ * If a control node reboots or reloads it's n2rng driver, this won't
+ * work during that time. So we have to keep probing until the device
+ * becomes usable.
+ */
+static int n2rng_guest_check(struct n2rng *np)
+{
+ unsigned long ra = __pa(&np->test_data);
+
+ return n2rng_generic_read_data(ra);
+}
+
+static int n2rng_entropy_diag_read(struct n2rng *np, unsigned long unit,
+ u64 *pre_control, u64 pre_state,
+ u64 *buffer, unsigned long buf_len,
+ u64 *post_control, u64 post_state)
+{
+ unsigned long post_ctl_ra = __pa(post_control);
+ unsigned long pre_ctl_ra = __pa(pre_control);
+ unsigned long buffer_ra = __pa(buffer);
+ int err;
+
+ err = n2rng_generic_write_control(np, pre_ctl_ra, unit, pre_state);
+ if (err)
+ return err;
+
+ err = n2rng_generic_read_diag_data(np, unit,
+ buffer_ra, buf_len);
+
+ (void) n2rng_generic_write_control(np, post_ctl_ra, unit,
+ post_state);
+
+ return err;
+}
+
+static u64 advance_polynomial(u64 poly, u64 val, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int highbit_set = ((s64)val < 0);
+
+ val <<= 1;
+ if (highbit_set)
+ val ^= poly;
+ }
+
+ return val;
+}
+
+static int n2rng_test_buffer_find(struct n2rng *np, u64 val)
+{
+ int i, count = 0;
+
+ /* Purposefully skip over the first word. */
+ for (i = 1; i < SELFTEST_BUFFER_WORDS; i++) {
+ if (np->test_buffer[i] == val)
+ count++;
+ }
+ return count;
+}
+
+static void n2rng_dump_test_buffer(struct n2rng *np)
+{
+ int i;
+
+ for (i = 0; i < SELFTEST_BUFFER_WORDS; i++)
+ dev_err(&np->op->dev, "Test buffer slot %d [0x%016lx]\n",
+ i, np->test_buffer[i]);
+}
+
+static int n2rng_check_selftest_buffer(struct n2rng *np, unsigned long unit)
+{
+ u64 val = SELFTEST_VAL;
+ int err, matches, limit;
+
+ matches = 0;
+ for (limit = 0; limit < SELFTEST_LOOPS_MAX; limit++) {
+ matches += n2rng_test_buffer_find(np, val);
+ if (matches >= SELFTEST_MATCH_GOAL)
+ break;
+ val = advance_polynomial(SELFTEST_POLY, val, 1);
+ }
+
+ err = 0;
+ if (limit >= SELFTEST_LOOPS_MAX) {
+ err = -ENODEV;
+ dev_err(&np->op->dev, "Selftest failed on unit %lu\n", unit);
+ n2rng_dump_test_buffer(np);
+ } else
+ dev_info(&np->op->dev, "Selftest passed on unit %lu\n", unit);
+
+ return err;
+}
+
+static int n2rng_control_selftest(struct n2rng *np, unsigned long unit)
+{
+ int err;
+
+ np->test_control[0] = (0x2 << RNG_CTL_ASEL_SHIFT);
+ np->test_control[1] = (0x2 << RNG_CTL_ASEL_SHIFT);
+ np->test_control[2] = (0x2 << RNG_CTL_ASEL_SHIFT);
+ np->test_control[3] = ((0x2 << RNG_CTL_ASEL_SHIFT) |
+ RNG_CTL_LFSR |
+ ((SELFTEST_TICKS - 2) << RNG_CTL_WAIT_SHIFT));
+
+
+ err = n2rng_entropy_diag_read(np, unit, np->test_control,
+ HV_RNG_STATE_HEALTHCHECK,
+ np->test_buffer,
+ sizeof(np->test_buffer),
+ &np->units[unit].control[0],
+ np->hv_state);
+ if (err)
+ return err;
+
+ return n2rng_check_selftest_buffer(np, unit);
+}
+
+static int n2rng_control_check(struct n2rng *np)
+{
+ int i;
+
+ for (i = 0; i < np->num_units; i++) {
+ int err = n2rng_control_selftest(np, i);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+/* The sanity checks passed, install the final configuration into the
+ * chip, it's ready to use.
+ */
+static int n2rng_control_configure_units(struct n2rng *np)
+{
+ int unit, err;
+
+ err = 0;
+ for (unit = 0; unit < np->num_units; unit++) {
+ struct n2rng_unit *up = &np->units[unit];
+ unsigned long ctl_ra = __pa(&up->control[0]);
+ int esrc;
+ u64 base;
+
+ base = ((np->accum_cycles << RNG_CTL_WAIT_SHIFT) |
+ (2 << RNG_CTL_ASEL_SHIFT) |
+ RNG_CTL_LFSR);
+
+ /* XXX This isn't the best. We should fetch a bunch
+ * XXX of words using each entropy source combined XXX
+ * with each VCO setting, and see which combinations
+ * XXX give the best random data.
+ */
+ for (esrc = 0; esrc < 3; esrc++)
+ up->control[esrc] = base |
+ (esrc << RNG_CTL_VCO_SHIFT) |
+ (RNG_CTL_ES1 << esrc);
+
+ up->control[3] = base |
+ (RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3);
+
+ err = n2rng_generic_write_control(np, ctl_ra, unit,
+ HV_RNG_STATE_CONFIGURED);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
+static void n2rng_work(struct work_struct *work)
+{
+ struct n2rng *np = container_of(work, struct n2rng, work.work);
+ int err = 0;
+
+ if (!(np->flags & N2RNG_FLAG_CONTROL)) {
+ err = n2rng_guest_check(np);
+ } else {
+ preempt_disable();
+ err = n2rng_control_check(np);
+ preempt_enable();
+
+ if (!err)
+ err = n2rng_control_configure_units(np);
+ }
+
+ if (!err) {
+ np->flags |= N2RNG_FLAG_READY;
+ dev_info(&np->op->dev, "RNG ready\n");
+ }
+
+ if (err && !(np->flags & N2RNG_FLAG_SHUTDOWN))
+ schedule_delayed_work(&np->work, HZ * 2);
+}
+
+static void __devinit n2rng_driver_version(void)
+{
+ static int n2rng_version_printed;
+
+ if (n2rng_version_printed++ == 0)
+ pr_info("%s", version);
+}
+
+static int __devinit n2rng_probe(struct of_device *op,
+ const struct of_device_id *match)
+{
+ int victoria_falls = (match->data != NULL);
+ int err = -ENOMEM;
+ struct n2rng *np;
+
+ n2rng_driver_version();
+
+ np = kzalloc(sizeof(*np), GFP_KERNEL);
+ if (!np)
+ goto out;
+ np->op = op;
+
+ INIT_DELAYED_WORK(&np->work, n2rng_work);
+
+ if (victoria_falls)
+ np->flags |= N2RNG_FLAG_VF;
+
+ err = -ENODEV;
+ np->hvapi_major = 2;
+ if (sun4v_hvapi_register(HV_GRP_RNG,
+ np->hvapi_major,
+ &np->hvapi_minor)) {
+ np->hvapi_major = 1;
+ if (sun4v_hvapi_register(HV_GRP_RNG,
+ np->hvapi_major,
+ &np->hvapi_minor)) {
+ dev_err(&op->dev, "Cannot register suitable "
+ "HVAPI version.\n");
+ goto out_free;
+ }
+ }
+
+ if (np->flags & N2RNG_FLAG_VF) {
+ if (np->hvapi_major < 2) {
+ dev_err(&op->dev, "VF RNG requires HVAPI major "
+ "version 2 or later, got %lu\n",
+ np->hvapi_major);
+ goto out_hvapi_unregister;
+ }
+ np->num_units = of_getintprop_default(op->node,
+ "rng-#units", 0);
+ if (!np->num_units) {
+ dev_err(&op->dev, "VF RNG lacks rng-#units property\n");
+ goto out_hvapi_unregister;
+ }
+ } else
+ np->num_units = 1;
+
+ dev_info(&op->dev, "Registered RNG HVAPI major %lu minor %lu\n",
+ np->hvapi_major, np->hvapi_minor);
+
+ np->units = kzalloc(sizeof(struct n2rng_unit) * np->num_units,
+ GFP_KERNEL);
+ err = -ENOMEM;
+ if (!np->units)
+ goto out_hvapi_unregister;
+
+ err = n2rng_init_control(np);
+ if (err)
+ goto out_free_units;
+
+ dev_info(&op->dev, "Found %s RNG, units: %d\n",
+ ((np->flags & N2RNG_FLAG_VF) ?
+ "Victoria Falls" : "Niagara2"),
+ np->num_units);
+
+ np->hwrng.name = "n2rng";
+ np->hwrng.data_read = n2rng_data_read;
+ np->hwrng.priv = (unsigned long) np;
+
+ err = hwrng_register(&np->hwrng);
+ if (err)
+ goto out_free_units;
+
+ dev_set_drvdata(&op->dev, np);
+
+ schedule_delayed_work(&np->work, 0);
+
+ return 0;
+
+out_free_units:
+ kfree(np->units);
+ np->units = NULL;
+
+out_hvapi_unregister:
+ sun4v_hvapi_unregister(HV_GRP_RNG);
+
+out_free:
+ kfree(np);
+out:
+ return err;
+}
+
+static int __devexit n2rng_remove(struct of_device *op)
+{
+ struct n2rng *np = dev_get_drvdata(&op->dev);
+
+ np->flags |= N2RNG_FLAG_SHUTDOWN;
+
+ cancel_delayed_work_sync(&np->work);
+
+ hwrng_unregister(&np->hwrng);
+
+ sun4v_hvapi_unregister(HV_GRP_RNG);
+
+ kfree(np->units);
+ np->units = NULL;
+
+ kfree(np);
+
+ dev_set_drvdata(&op->dev, NULL);
+
+ return 0;
+}
+
+static struct of_device_id n2rng_match[] = {
+ {
+ .name = "random-number-generator",
+ .compatible = "SUNW,n2-rng",
+ },
+ {
+ .name = "random-number-generator",
+ .compatible = "SUNW,vf-rng",
+ .data = (void *) 1,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, n2rng_match);
+
+static struct of_platform_driver n2rng_driver = {
+ .name = "n2rng",
+ .match_table = n2rng_match,
+ .probe = n2rng_probe,
+ .remove = __devexit_p(n2rng_remove),
+};
+
+static int __init n2rng_init(void)
+{
+ return of_register_driver(&n2rng_driver, &of_bus_type);
+}
+
+static void __exit n2rng_exit(void)
+{
+ of_unregister_driver(&n2rng_driver);
+}
+
+module_init(n2rng_init);
+module_exit(n2rng_exit);
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h
new file mode 100644
index 00000000000..a2b81e7bfc1
--- /dev/null
+++ b/drivers/char/hw_random/n2rng.h
@@ -0,0 +1,118 @@
+/* n2rng.h: Niagara2 RNG defines.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#ifndef _N2RNG_H
+#define _N2RNG_H
+
+#define RNG_CTL_WAIT 0x0000000001fffe00ULL /* Minimum wait time */
+#define RNG_CTL_WAIT_SHIFT 9
+#define RNG_CTL_BYPASS 0x0000000000000100ULL /* VCO voltage source */
+#define RNG_CTL_VCO 0x00000000000000c0ULL /* VCO rate control */
+#define RNG_CTL_VCO_SHIFT 6
+#define RNG_CTL_ASEL 0x0000000000000030ULL /* Analog MUX select */
+#define RNG_CTL_ASEL_SHIFT 4
+#define RNG_CTL_LFSR 0x0000000000000008ULL /* Use LFSR or plain shift */
+#define RNG_CTL_ES3 0x0000000000000004ULL /* Enable entropy source 3 */
+#define RNG_CTL_ES2 0x0000000000000002ULL /* Enable entropy source 2 */
+#define RNG_CTL_ES1 0x0000000000000001ULL /* Enable entropy source 1 */
+
+#define HV_FAST_RNG_GET_DIAG_CTL 0x130
+#define HV_FAST_RNG_CTL_READ 0x131
+#define HV_FAST_RNG_CTL_WRITE 0x132
+#define HV_FAST_RNG_DATA_READ_DIAG 0x133
+#define HV_FAST_RNG_DATA_READ 0x134
+
+#define HV_RNG_STATE_UNCONFIGURED 0
+#define HV_RNG_STATE_CONFIGURED 1
+#define HV_RNG_STATE_HEALTHCHECK 2
+#define HV_RNG_STATE_ERROR 3
+
+#define HV_RNG_NUM_CONTROL 4
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_rng_get_diag_ctl(void);
+extern unsigned long sun4v_rng_ctl_read_v1(unsigned long ctl_regs_ra,
+ unsigned long *state,
+ unsigned long *tick_delta);
+extern unsigned long sun4v_rng_ctl_read_v2(unsigned long ctl_regs_ra,
+ unsigned long unit,
+ unsigned long *state,
+ unsigned long *tick_delta,
+ unsigned long *watchdog,
+ unsigned long *write_status);
+extern unsigned long sun4v_rng_ctl_write_v1(unsigned long ctl_regs_ra,
+ unsigned long state,
+ unsigned long write_timeout,
+ unsigned long *tick_delta);
+extern unsigned long sun4v_rng_ctl_write_v2(unsigned long ctl_regs_ra,
+ unsigned long state,
+ unsigned long write_timeout,
+ unsigned long unit);
+extern unsigned long sun4v_rng_data_read_diag_v1(unsigned long data_ra,
+ unsigned long len,
+ unsigned long *tick_delta);
+extern unsigned long sun4v_rng_data_read_diag_v2(unsigned long data_ra,
+ unsigned long len,
+ unsigned long unit,
+ unsigned long *tick_delta);
+extern unsigned long sun4v_rng_data_read(unsigned long data_ra,
+ unsigned long *tick_delta);
+
+struct n2rng_unit {
+ u64 control[HV_RNG_NUM_CONTROL];
+};
+
+struct n2rng {
+ struct of_device *op;
+
+ unsigned long flags;
+#define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */
+#define N2RNG_FLAG_CONTROL 0x00000002 /* Operating in control domain */
+#define N2RNG_FLAG_READY 0x00000008 /* Ready for hw-rng layer */
+#define N2RNG_FLAG_SHUTDOWN 0x00000010 /* Driver unregistering */
+#define N2RNG_FLAG_BUFFER_VALID 0x00000020 /* u32 buffer holds valid data */
+
+ int num_units;
+ struct n2rng_unit *units;
+
+ struct hwrng hwrng;
+ u32 buffer;
+
+ /* Registered hypervisor group API major and minor version. */
+ unsigned long hvapi_major;
+ unsigned long hvapi_minor;
+
+ struct delayed_work work;
+
+ unsigned long hv_state; /* HV_RNG_STATE_foo */
+
+ unsigned long health_check_sec;
+ unsigned long accum_cycles;
+ unsigned long wd_timeo;
+#define N2RNG_HEALTH_CHECK_SEC_DEFAULT 0
+#define N2RNG_ACCUM_CYCLES_DEFAULT 2048
+#define N2RNG_WD_TIMEO_DEFAULT 0
+
+ u64 scratch_control[HV_RNG_NUM_CONTROL];
+
+#define SELFTEST_TICKS 38859
+#define SELFTEST_VAL ((u64)0xB8820C7BD387E32C)
+#define SELFTEST_POLY ((u64)0x231DCEE91262B8A3)
+#define SELFTEST_MATCH_GOAL 6
+#define SELFTEST_LOOPS_MAX 40000
+#define SELFTEST_BUFFER_WORDS 8
+
+ u64 test_data;
+ u64 test_control[HV_RNG_NUM_CONTROL];
+ u64 test_buffer[SELFTEST_BUFFER_WORDS];
+};
+
+#define N2RNG_BLOCK_LIMIT 60000
+#define N2RNG_BUSY_LIMIT 100
+#define N2RNG_HCHECK_LIMIT 100
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* _N2RNG_H */
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 5dc74404058..9cb48fcd316 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- device_create(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i),
- "ipl%d", i);
- device_create(ip2_class, NULL,
- MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
- "stat%d", i);
+ device_create_drvdata(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i),
+ NULL, "ipl%d", i);
+ device_create_drvdata(ip2_class, NULL,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+ NULL, "stat%d", i);
for ( box = 0; box < ABS_MAX_BOXES; ++box )
{
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index c11a4048345..64e1c169e82 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
entry->dev = dev;
mutex_lock(&reg_list_mutex);
- device_create(ipmi_class, device, dev, "ipmi%d", if_num);
+ device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
list_add(&entry->link, &reg_list);
mutex_unlock(&reg_list_mutex);
}
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index d4281df10c2..8f7cc190b62 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1181,14 +1181,17 @@ static int isicom_chars_in_buffer(struct tty_struct *tty)
}
/* ioctl et all */
-static inline void isicom_send_break(struct isi_port *port,
- unsigned long length)
+static int isicom_send_break(struct tty_struct *tty, int length)
{
+ struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card;
unsigned long base = card->base;
+ if (length == -1)
+ return -EOPNOTSUPP;
+
if (!lock_card(card))
- return;
+ return -EINVAL;
outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
outw((length & 0xff) << 8 | 0x00, base);
@@ -1196,6 +1199,7 @@ static inline void isicom_send_break(struct isi_port *port,
InterruptTheCard(base);
unlock_card(card);
+ return 0;
}
static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1305,28 +1309,11 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
{
struct isi_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
- int retval;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
switch (cmd) {
- case TCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- isicom_send_break(port, HZ/4);
- return 0;
-
- case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
- return 0;
case TIOCGSERIAL:
return isicom_get_serial_info(port, argp);
@@ -1459,6 +1446,7 @@ static const struct tty_operations isicom_ops = {
.flush_buffer = isicom_flush_buffer,
.tiocmget = isicom_tiocmget,
.tiocmset = isicom_tiocmset,
+ .break_ctl = isicom_send_break,
};
static int __devinit reset_card(struct pci_dev *pdev,
@@ -1832,7 +1820,7 @@ static int __init isicom_init(void)
isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
CLOCAL;
isicom_normal->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV;
+ TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(isicom_normal, &isicom_ops);
retval = tty_register_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 6ef1c565705..843a2afaf20 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -598,7 +598,7 @@ static int stli_parsebrd(struct stlconf *confp, char **argp);
static int stli_open(struct tty_struct *tty, struct file *filp);
static void stli_close(struct tty_struct *tty, struct file *filp);
static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void stli_putchar(struct tty_struct *tty, unsigned char ch);
+static int stli_putchar(struct tty_struct *tty, unsigned char ch);
static void stli_flushchars(struct tty_struct *tty);
static int stli_writeroom(struct tty_struct *tty);
static int stli_charsinbuffer(struct tty_struct *tty);
@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty);
static void stli_stop(struct tty_struct *tty);
static void stli_start(struct tty_struct *tty);
static void stli_flushbuffer(struct tty_struct *tty);
-static void stli_breakctl(struct tty_struct *tty, int state);
+static int stli_breakctl(struct tty_struct *tty, int state);
static void stli_waituntilsent(struct tty_struct *tty, int timeout);
static void stli_sendxchar(struct tty_struct *tty, char ch);
static void stli_hangup(struct tty_struct *tty);
@@ -826,7 +826,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
*/
portp->port.tty = tty;
tty->driver_data = portp;
- portp->refcount++;
+ portp->port.count++;
wait_event_interruptible(portp->raw_wait,
!test_bit(ST_INITIALIZING, &portp->state));
@@ -888,9 +888,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
spin_unlock_irqrestore(&stli_lock, flags);
return;
}
- if ((tty->count == 1) && (portp->refcount != 1))
- portp->refcount = 1;
- if (portp->refcount-- > 1) {
+ if ((tty->count == 1) && (portp->port.count != 1))
+ portp->port.count = 1;
+ if (portp->port.count-- > 1) {
spin_unlock_irqrestore(&stli_lock, flags);
return;
}
@@ -925,8 +925,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
- if (tty->ldisc.flush_buffer)
- (tty->ldisc.flush_buffer)(tty);
+ tty_ldisc_flush(tty);
set_bit(ST_DOFLUSHRX, &portp->state);
stli_flushbuffer(tty);
@@ -1202,7 +1201,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct
spin_lock_irqsave(&stli_lock, flags);
portp->openwaitcnt++;
if (! tty_hung_up_p(filp))
- portp->refcount--;
+ portp->port.count--;
spin_unlock_irqrestore(&stli_lock, flags);
for (;;) {
@@ -1231,7 +1230,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct
spin_lock_irqsave(&stli_lock, flags);
if (! tty_hung_up_p(filp))
- portp->refcount++;
+ portp->port.count++;
portp->openwaitcnt--;
spin_unlock_irqrestore(&stli_lock, flags);
@@ -1333,7 +1332,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun
* first them do the new ports.
*/
-static void stli_putchar(struct tty_struct *tty, unsigned char ch)
+static int stli_putchar(struct tty_struct *tty, unsigned char ch)
{
if (tty != stli_txcooktty) {
if (stli_txcooktty != NULL)
@@ -1342,6 +1341,7 @@ static void stli_putchar(struct tty_struct *tty, unsigned char ch)
}
stli_txcookbuf[stli_txcooksize++] = ch;
+ return 0;
}
/*****************************************************************************/
@@ -1660,7 +1660,6 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
{
struct stliport *portp;
struct stlibrd *brdp;
- unsigned int ival;
int rc;
void __user *argp = (void __user *)arg;
@@ -1857,7 +1856,7 @@ static void stli_hangup(struct tty_struct *tty)
set_bit(TTY_IO_ERROR, &tty->flags);
portp->port.tty = NULL;
portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- portp->refcount = 0;
+ portp->port.count = 0;
spin_unlock_irqrestore(&stli_lock, flags);
wake_up_interruptible(&portp->port.open_wait);
@@ -1909,7 +1908,7 @@ static void stli_flushbuffer(struct tty_struct *tty)
/*****************************************************************************/
-static void stli_breakctl(struct tty_struct *tty, int state)
+static int stli_breakctl(struct tty_struct *tty, int state)
{
struct stlibrd *brdp;
struct stliport *portp;
@@ -1917,15 +1916,16 @@ static void stli_breakctl(struct tty_struct *tty, int state)
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
if (portp->brdnr >= stli_nrbrds)
- return;
+ return -EINVAL;
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
- return;
+ return -EINVAL;
arg = (state == -1) ? BREAKON : BREAKOFF;
stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
+ return 0;
}
/*****************************************************************************/
@@ -4246,7 +4246,7 @@ static int stli_portcmdstats(struct stliport *portp)
stli_comstats.panel = portp->panelnr;
stli_comstats.port = portp->portnr;
stli_comstats.state = portp->state;
- stli_comstats.flags = portp->port.flag;
+ stli_comstats.flags = portp->port.flags;
spin_lock_irqsave(&brd_lock, flags);
if (portp->port.tty != NULL) {
@@ -4599,8 +4599,9 @@ static int __init istallion_module_init(void)
istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++)
- device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
- "staliomem%d", i);
+ device_create_drvdata(istallion_class, NULL,
+ MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_deinit:
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index d9a0a53c842..7b3a212c86b 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -46,6 +46,8 @@
extern void ctrl_alt_del(void);
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
+
/*
* Exported functions/variables
*/
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c
deleted file mode 100644
index 1c29b20e4f4..00000000000
--- a/drivers/char/lcd.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * LCD, LED and Button interface for Cobalt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- * March 2001: Ported from 2.0.34 by Liam Davies
- *
- */
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/mc146818rtc.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "lcd.h"
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-
-static unsigned int lcd_present = 1;
-
-/* used in arch/mips/cobalt/reset.c */
-int led_state = 0;
-
-#if defined(CONFIG_TULIP) && 0
-
-#define MAX_INTERFACES 8
-static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES];
-static void *linkcheck_cookies[MAX_INTERFACES];
-
-int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie)
-{
- if (iface_num < 0 ||
- iface_num >= MAX_INTERFACES ||
- linkcheck_callbacks[iface_num] != NULL)
- return -1;
- linkcheck_callbacks[iface_num] = (linkcheck_func_t) func;
- linkcheck_cookies[iface_num] = cookie;
- return 0;
-}
-#endif
-
-static int lcd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct lcd_display button_display;
- unsigned long address, a;
-
- switch (cmd) {
- case LCD_On:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0F);
- break;
-
- case LCD_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x08);
- break;
-
- case LCD_Reset:
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x3F);
- udelay(150);
- LCDWriteInst(0x01);
- udelay(150);
- LCDWriteInst(0x06);
- break;
-
- case LCD_Clear:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x01);
- break;
-
- case LCD_Cursor_Left:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
- break;
-
- case LCD_Cursor_Right:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x14);
- break;
-
- case LCD_Cursor_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0C);
- break;
-
- case LCD_Cursor_On:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0F);
- break;
-
- case LCD_Blink_Off:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x0E);
- break;
-
- case LCD_Get_Cursor_Pos:{
- struct lcd_display display;
-
- udelay(150);
- BusyCheck();
- display.cursor_address = (LCDReadInst);
- display.cursor_address =
- (display.cursor_address & 0x07F);
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- break;
- }
-
-
- case LCD_Set_Cursor_Pos:{
- struct lcd_display display;
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- a = (display.cursor_address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
-
- break;
- }
-
- case LCD_Get_Cursor:{
- struct lcd_display display;
-
- udelay(150);
- BusyCheck();
- display.character = LCDReadData;
-
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
-
- break;
- }
-
- case LCD_Set_Cursor:{
- struct lcd_display display;
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- udelay(150);
- BusyCheck();
- LCDWriteData(display.character);
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x10);
-
- break;
- }
-
-
- case LCD_Disp_Left:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x18);
- break;
-
- case LCD_Disp_Right:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x1C);
- break;
-
- case LCD_Home:
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x02);
- break;
-
- case LCD_Write:{
- struct lcd_display display;
- unsigned int index;
-
-
- if (copy_from_user
- (&display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(0x80);
- udelay(150);
- BusyCheck();
-
- for (index = 0; index < (display.size1); index++) {
- udelay(150);
- BusyCheck();
- LCDWriteData(display.line1[index]);
- BusyCheck();
- }
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(0xC0);
- udelay(150);
- BusyCheck();
- for (index = 0; index < (display.size2); index++) {
- udelay(150);
- BusyCheck();
- LCDWriteData(display.line2[index]);
- }
-
- break;
- }
-
- case LCD_Read:{
- struct lcd_display display;
-
- BusyCheck();
- for (address = kDD_R00; address <= kDD_R01;
- address++) {
- a = (address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
- udelay(150);
- BusyCheck();
- display.line1[address] = LCDReadData;
- }
-
- display.line1[0x27] = '\0';
-
- for (address = kDD_R10; address <= kDD_R11;
- address++) {
- a = (address | kLCD_Addr);
-
- udelay(150);
- BusyCheck();
- LCDWriteInst(a);
-
- udelay(150);
- BusyCheck();
- display.line2[address - 0x40] =
- LCDReadData;
- }
-
- display.line2[0x27] = '\0';
-
- if (copy_to_user
- ((struct lcd_display *) arg, &display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
-// set all GPIO leds to led_display.leds
-
- case LED_Set:{
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- led_state = led_display.leds;
- LEDSet(led_state);
-
- break;
- }
-
-
-// set only bit led_display.leds
-
- case LED_Bit_Set:{
- unsigned int i;
- int bit = 1;
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- for (i = 0; i < (int) led_display.leds; i++) {
- bit = 2 * bit;
- }
-
- led_state = led_state | bit;
- LEDSet(led_state);
- break;
- }
-
-// clear only bit led_display.leds
-
- case LED_Bit_Clear:{
- unsigned int i;
- int bit = 1;
- struct lcd_display led_display;
-
-
- if (copy_from_user
- (&led_display, (struct lcd_display *) arg,
- sizeof(struct lcd_display)))
- return -EFAULT;
-
- for (i = 0; i < (int) led_display.leds; i++) {
- bit = 2 * bit;
- }
-
- led_state = led_state & ~bit;
- LEDSet(led_state);
- break;
- }
-
-
- case BUTTON_Read:{
- button_display.buttons = GPIRead;
- if (copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- case LINK_Check:{
- button_display.buttons =
- *((volatile unsigned long *) (0xB0100060));
- if (copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- case LINK_Check_2:{
- int iface_num;
-
- /* panel-utils should pass in the desired interface status is wanted for
- * in "buttons" of the structure. We will set this to non-zero if the
- * link is in fact up for the requested interface. --DaveM
- */
- if (copy_from_user
- (&button_display, (struct lcd_display *) arg,
- sizeof(button_display)))
- return -EFAULT;
- iface_num = button_display.buttons;
-#if defined(CONFIG_TULIP) && 0
- if (iface_num >= 0 &&
- iface_num < MAX_INTERFACES &&
- linkcheck_callbacks[iface_num] != NULL) {
- button_display.buttons =
- linkcheck_callbacks[iface_num]
- (linkcheck_cookies[iface_num]);
- } else
-#endif
- button_display.buttons = 0;
-
- if (__copy_to_user
- ((struct lcd_display *) arg, &button_display,
- sizeof(struct lcd_display)))
- return -EFAULT;
- break;
- }
-
- default:
- return -EINVAL;
-
- }
-
- return 0;
-
-}
-
-static int lcd_open(struct inode *inode, struct file *file)
-{
- cycle_kernel_lock();
-
- if (!lcd_present)
- return -ENXIO;
- else
- return 0;
-}
-
-/* Only RESET or NEXT counts as button pressed */
-
-static inline int button_pressed(void)
-{
- unsigned long buttons = GPIRead;
-
- if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B)
- || (buttons == BUTTON_Reset_B))
- return buttons;
- return 0;
-}
-
-/* LED daemon sits on this and we wake him up once a key is pressed. */
-
-static int lcd_waiters = 0;
-
-static ssize_t lcd_read(struct file *file, char *buf,
- size_t count, loff_t *ofs)
-{
- long buttons_now;
-
- if (lcd_waiters > 0)
- return -EINVAL;
-
- lcd_waiters++;
- while (((buttons_now = (long) button_pressed()) == 0) &&
- !(signal_pending(current))) {
- msleep_interruptible(2000);
- }
- lcd_waiters--;
-
- if (signal_pending(current))
- return -ERESTARTSYS;
- return buttons_now;
-}
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations lcd_fops = {
- .read = lcd_read,
- .ioctl = lcd_ioctl,
- .open = lcd_open,
-};
-
-static struct miscdevice lcd_dev = {
- MISC_DYNAMIC_MINOR,
- "lcd",
- &lcd_fops
-};
-
-static int lcd_init(void)
-{
- int ret;
- unsigned long data;
-
- pr_info("%s\n", LCD_DRIVER);
- ret = misc_register(&lcd_dev);
- if (ret) {
- printk(KERN_WARNING LCD "Unable to register misc device.\n");
- return ret;
- }
-
- /* Check region? Naaah! Just snarf it up. */
-/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
-
- udelay(150);
- data = LCDReadData;
- if ((data & 0x000000FF) == (0x00)) {
- lcd_present = 0;
- pr_info(LCD "LCD Not Present\n");
- } else {
- lcd_present = 1;
- WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg);
- WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg);
- }
-
- return 0;
-}
-
-static void __exit lcd_exit(void)
-{
- misc_deregister(&lcd_dev);
-}
-
-module_init(lcd_init);
-module_exit(lcd_exit);
-
-MODULE_AUTHOR("Andrew Bose");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
deleted file mode 100644
index 290b3ff23b0..00000000000
--- a/drivers/char/lcd.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * LED, LCD and Button panel driver for Cobalt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997 by Andrew Bose
- *
- * Linux kernel version history:
- * March 2001: Ported from 2.0.34 by Liam Davies
- *
- */
-
-// function headers
-
-#define LCD_CHARS_PER_LINE 40
-#define MAX_IDLE_TIME 120
-
-struct lcd_display {
- unsigned buttons;
- int size1;
- int size2;
- unsigned char line1[LCD_CHARS_PER_LINE];
- unsigned char line2[LCD_CHARS_PER_LINE];
- unsigned char cursor_address;
- unsigned char character;
- unsigned char leds;
- unsigned char *RomImage;
-};
-
-
-
-#define LCD_DRIVER "Cobalt LCD Driver v2.10"
-
-#define LCD "lcd: "
-
-#define kLCD_IR 0x0F000000
-#define kLCD_DR 0x0F000010
-#define kGPI 0x0D000000
-#define kLED 0x0C000000
-
-#define kDD_R00 0x00
-#define kDD_R01 0x27
-#define kDD_R10 0x40
-#define kDD_R11 0x67
-
-#define kLCD_Addr 0x00000080
-
-#define LCDTimeoutValue 0xfff
-
-
-// Macros
-
-#define LCDWriteData(x) outl((x << 24), kLCD_DR)
-#define LCDWriteInst(x) outl((x << 24), kLCD_IR)
-
-#define LCDReadData (inl(kLCD_DR) >> 24)
-#define LCDReadInst (inl(kLCD_IR) >> 24)
-
-#define GPIRead (inl(kGPI) >> 24)
-
-#define LEDSet(x) outb((char)x, kLED)
-
-#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x))
-#define BusyCheck() while ((LCDReadInst & 0x80) == 0x80)
-
-
-
-/*
- * Function command codes for io_ctl.
- */
-#define LCD_On 1
-#define LCD_Off 2
-#define LCD_Clear 3
-#define LCD_Reset 4
-#define LCD_Cursor_Left 5
-#define LCD_Cursor_Right 6
-#define LCD_Disp_Left 7
-#define LCD_Disp_Right 8
-#define LCD_Get_Cursor 9
-#define LCD_Set_Cursor 10
-#define LCD_Home 11
-#define LCD_Read 12
-#define LCD_Write 13
-#define LCD_Cursor_Off 14
-#define LCD_Cursor_On 15
-#define LCD_Get_Cursor_Pos 16
-#define LCD_Set_Cursor_Pos 17
-#define LCD_Blink_Off 18
-
-#define LED_Set 40
-#define LED_Bit_Set 41
-#define LED_Bit_Clear 42
-
-
-// Button defs
-#define BUTTON_Read 50
-
-
-// Ethernet LINK check hackaroo
-#define LINK_Check 90
-#define LINK_Check_2 91
-
-// Button patterns _B - single layer lcd boards
-
-#define BUTTON_NONE 0x3F
-#define BUTTON_NONE_B 0xFE
-
-#define BUTTON_Left 0x3B
-#define BUTTON_Left_B 0xFA
-
-#define BUTTON_Right 0x37
-#define BUTTON_Right_B 0xDE
-
-#define BUTTON_Up 0x2F
-#define BUTTON_Up_B 0xF6
-
-#define BUTTON_Down 0x1F
-#define BUTTON_Down_B 0xEE
-
-#define BUTTON_Next 0x3D
-#define BUTTON_Next_B 0x7E
-
-#define BUTTON_Enter 0x3E
-#define BUTTON_Enter_B 0xBE
-
-#define BUTTON_Reset_B 0xFC
-
-
-// debounce constants
-
-#define BUTTON_SENSE 160000
-#define BUTTON_DEBOUNCE 5000
-
-
-// Galileo register stuff
-
-#define kGal_DevBank2Cfg 0x1466DB33
-#define kGal_DevBank2PReg 0x464
-#define kGal_DevBank3Cfg 0x146FDFFB
-#define kGal_DevBank3PReg 0x468
-
-// Network
-
-#define kIPADDR 1
-#define kNETMASK 2
-#define kGATEWAY 3
-#define kDNS 4
-
-#define kClassA 5
-#define kClassB 6
-#define kClassC 7
-
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 71abb4c33aa..3f2719b9f77 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -813,7 +813,8 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);
+ device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+ "lp%d", nr);
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
(port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 070e22e8ea9..672b08e694d 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -80,7 +80,7 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
}
#endif
-#ifdef CONFIG_NONPROMISC_DEVMEM
+#ifdef CONFIG_STRICT_DEVMEM
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
u64 from = ((u64)pfn) << PAGE_SHIFT;
@@ -327,7 +327,10 @@ static void mmap_mem_close(struct vm_area_struct *vma)
static struct vm_operations_struct mmap_mem_ops = {
.open = mmap_mem_open,
- .close = mmap_mem_close
+ .close = mmap_mem_close,
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+ .access = generic_access_phys
+#endif
};
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
@@ -989,9 +992,9 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++)
- device_create(mem_class, NULL,
- MKDEV(MEM_MAJOR, devlist[i].minor),
- devlist[i].name);
+ device_create_drvdata(mem_class, NULL,
+ MKDEV(MEM_MAJOR, devlist[i].minor),
+ NULL, devlist[i].name);
return 0;
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 6e1563c3d30..999aa779c08 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->this_device = device_create(misc_class, misc->parent, dev,
- "%s", misc->name);
+ misc->this_device = device_create_drvdata(misc_class, misc->parent,
+ dev, NULL, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->this_device);
goto out;
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 192961fd717..918711aa56f 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/math64.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/sn/addrs.h>
@@ -57,8 +58,8 @@ extern unsigned long sn_rtc_cycles_per_second;
#define rtc_time() (*RTC_COUNTER_ADDR)
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
/*
@@ -67,9 +68,9 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
static unsigned long mmtimer_femtoperiod = 0;
static const struct file_operations mmtimer_fops = {
- .owner = THIS_MODULE,
- .mmap = mmtimer_mmap,
- .ioctl = mmtimer_ioctl,
+ .owner = THIS_MODULE,
+ .mmap = mmtimer_mmap,
+ .unlocked_ioctl = mmtimer_ioctl,
};
/*
@@ -339,7 +340,6 @@ restart:
/**
* mmtimer_ioctl - ioctl interface for /dev/mmtimer
- * @inode: inode of the device
* @file: file structure for the device
* @cmd: command to execute
* @arg: optional argument to command
@@ -365,11 +365,13 @@ restart:
* %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
* in the address specified by @arg.
*/
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int ret = 0;
+ lock_kernel();
+
switch (cmd) {
case MMTIMER_GETOFFSET: /* offset of the counter */
/*
@@ -384,15 +386,14 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file,
case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
if(copy_to_user((unsigned long __user *)arg,
&mmtimer_femtoperiod, sizeof(unsigned long)))
- return -EFAULT;
+ ret = -EFAULT;
break;
case MMTIMER_GETFREQ: /* frequency in Hz */
if(copy_to_user((unsigned long __user *)arg,
&sn_rtc_cycles_per_second,
sizeof(unsigned long)))
- return -EFAULT;
- ret = 0;
+ ret = -EFAULT;
break;
case MMTIMER_GETBITS: /* number of bits in the clock */
@@ -406,13 +407,13 @@ static int mmtimer_ioctl(struct inode *inode, struct file *file,
case MMTIMER_GETCOUNTER:
if(copy_to_user((unsigned long __user *)arg,
RTC_COUNTER_ADDR, sizeof(unsigned long)))
- return -EFAULT;
+ ret = -EFAULT;
break;
default:
- ret = -ENOSYS;
+ ret = -ENOTTY;
break;
}
-
+ unlock_kernel();
return ret;
}
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 2bba250ffc8..d3d7864e0c1 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -374,12 +374,13 @@ copy:
return ret;
}
-static void moxa_break_ctl(struct tty_struct *tty, int state)
+static int moxa_break_ctl(struct tty_struct *tty, int state)
{
struct moxa_port *port = tty->driver_data;
moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
Magic_code);
+ return 0;
}
static const struct tty_operations moxa_ops = {
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index fe2a95b5d3c..30f095a8c2d 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -193,25 +193,23 @@ mspec_close(struct vm_area_struct *vma)
}
/*
- * mspec_nopfn
+ * mspec_fault
*
* Creates a mspec page and maps it to user space.
*/
-static unsigned long
-mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+static int
+mspec_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
unsigned long paddr, maddr;
unsigned long pfn;
- int index;
+ pgoff_t index = vmf->pgoff;
struct vma_data *vdata = vma->vm_private_data;
- BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
- index = (address - vdata->vm_start) >> PAGE_SHIFT;
maddr = (volatile unsigned long) vdata->maddr[index];
if (maddr == 0) {
maddr = uncached_alloc_page(numa_node_id(), 1);
if (maddr == 0)
- return NOPFN_OOM;
+ return VM_FAULT_OOM;
spin_lock(&vdata->lock);
if (vdata->maddr[index] == 0) {
@@ -231,13 +229,20 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
pfn = paddr >> PAGE_SHIFT;
- return pfn;
+ /*
+ * vm_insert_pfn can fail with -EBUSY, but in that case it will
+ * be because another thread has installed the pte first, so it
+ * is no problem.
+ */
+ vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+ return VM_FAULT_NOPAGE;
}
static struct vm_operations_struct mspec_vm_ops = {
.open = mspec_open,
.close = mspec_close,
- .nopfn = mspec_nopfn
+ .fault = mspec_fault,
};
/*
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 6307e301bd2..4c756bbba94 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -47,7 +47,7 @@
#include "mxser.h"
-#define MXSER_VERSION "2.0.3" /* 1.11 */
+#define MXSER_VERSION "2.0.4" /* 1.12 */
#define MXSERMAJOR 174
#define MXSERCUMAJOR 175
@@ -71,12 +71,13 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
+#define PCI_DEVICE_ID_POS104UL 0x1044
#define PCI_DEVICE_ID_CB108 0x1080
+#define PCI_DEVICE_ID_CP102UF 0x1023
#define PCI_DEVICE_ID_CB114 0x1142
#define PCI_DEVICE_ID_CP114UL 0x1143
#define PCI_DEVICE_ID_CB134I 0x1341
#define PCI_DEVICE_ID_CP138U 0x1380
-#define PCI_DEVICE_ID_POS104UL 0x1044
#define C168_ASIC_ID 1
@@ -142,7 +143,8 @@ static const struct mxser_cardinfo mxser_cards[] = {
{ "CB-134I series", 4, },
{ "CP-138U series", 8, },
{ "POS-104UL series", 4, },
- { "CP-114UL series", 4, }
+ { "CP-114UL series", 4, },
+/*30*/ { "CP-102UF series", 2, }
};
/* driver_data correspond to the lines in the structure above
@@ -172,6 +174,7 @@ static struct pci_device_id mxser_pcibrds[] = {
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 },
+ { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 },
{ }
};
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -1414,7 +1417,6 @@ static int mxser_set_serial_info(struct mxser_port *info,
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
info->port.tty->low_latency =
(info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
- info->port.tty->low_latency = 0;
if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(new_serial.baud_base != info->baud_base ||
new_serial.custom_divisor !=
@@ -1464,27 +1466,6 @@ static int mxser_get_lsr_info(struct mxser_port *info,
return put_user(result, value);
}
-/*
- * This routine sends a break character out the serial port.
- */
-static void mxser_send_break(struct mxser_port *info, int duration)
-{
- unsigned long flags;
-
- if (!info->ioaddr)
- return;
- set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
- info->ioaddr + UART_LCR);
- spin_unlock_irqrestore(&info->slock, flags);
- schedule_timeout(duration);
- spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
- info->ioaddr + UART_LCR);
- spin_unlock_irqrestore(&info->slock, flags);
-}
-
static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
{
struct mxser_port *info = tty->driver_data;
@@ -1872,21 +1853,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return -EIO;
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- mxser_send_break(info, HZ / 4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
- return 0;
case TIOCGSERIAL:
lock_kernel();
retval = mxser_get_serial_info(info, argp);
@@ -2219,7 +2185,7 @@ static void mxser_hangup(struct tty_struct *tty)
/*
* mxser_rs_break() --- routine which turns the break handling on or off
*/
-static void mxser_rs_break(struct tty_struct *tty, int break_state)
+static int mxser_rs_break(struct tty_struct *tty, int break_state)
{
struct mxser_port *info = tty->driver_data;
unsigned long flags;
@@ -2232,6 +2198,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state)
outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
info->ioaddr + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
}
static void mxser_receive_chars(struct mxser_port *port, int *status)
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index ed4e03333ab..69ec6399c71 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -677,6 +677,10 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
/* Allocate transmit buffer */
/* sleep until transmit buffer available */
while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) {
+ if (file->f_flags & O_NONBLOCK) {
+ error = -EAGAIN;
+ break;
+ }
schedule();
n_hdlc = tty2n_hdlc (tty);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index a22662b6a1a..39f6357e3b5 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -107,7 +107,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index e4a4fbd37d7..f070ae7bd91 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1896,7 +1896,7 @@ static int cm4000_probe(struct pcmcia_device *link)
return ret;
}
- device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i);
+ device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 6181f8a9b0b..0b5934bef7a 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -653,7 +653,8 @@ static int reader_probe(struct pcmcia_device *link)
return ret;
}
- device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i);
+ device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
+ "cmx%d", i);
return 0;
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index b694d430f10..d1fceabe3ae 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
* Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear
*/
-static void mgslpc_break(struct tty_struct *tty, int break_state)
+static int mgslpc_break(struct tty_struct *tty, int break_state)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags;
@@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->lock,flags);
if (break_state == -1)
@@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
else
clear_reg_bits(info, CHA+DAFO, BIT6);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
/* Service an IOCTL request
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index f6e6acadd9a..7af7a7e6b9c 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,8 +752,9 @@ static const struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
- "parport%d", port->number);
+ device_create_drvdata(ppdev_class, port->dev,
+ MKDEV(PP_MAJOR, port->number),
+ NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0cf98bd4f2d..e0d0e371909 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -236,6 +236,7 @@
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/percpu.h>
#include <linux/cryptohash.h>
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 505fcbe884a..47b8cf281d4 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
- "raw%d", rq->raw_minor);
+ device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
+ NULL, "raw%d", rq->raw_minor);
}
/*
@@ -283,7 +283,8 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class);
goto error_region;
}
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
+ device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
+ "rawctl");
return 0;
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 724b2b20f4b..2c6c8f33d6b 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1250,11 +1250,15 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
-static void rc_send_break(struct riscom_port *port, unsigned long length)
+static int rc_send_break(struct tty_struct *tty, int length)
{
+ struct riscom_port *port = (struct riscom_port *)tty->driver_data;
struct riscom_board *bp = port_Board(port);
unsigned long flags;
+ if (length == 0 || length == -1)
+ return -EOPNOTSUPP;
+
spin_lock_irqsave(&riscom_lock, flags);
port->break_length = RISCOM_TPS / HZ * length;
@@ -1268,6 +1272,7 @@ static void rc_send_break(struct riscom_port *port, unsigned long length)
rc_wait_CCR(bp);
spin_unlock_irqrestore(&riscom_lock, flags);
+ return 0;
}
static int rc_set_serial_info(struct riscom_port *port,
@@ -1342,27 +1347,12 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
{
struct riscom_port *port = (struct riscom_port *)tty->driver_data;
void __user *argp = (void __user *)arg;
- int retval = 0;
+ int retval;
if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
return -ENODEV;
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- rc_send_break(port, HZ/4); /* 1/4 second */
- break;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
- break;
case TIOCGSERIAL:
lock_kernel();
retval = rc_get_serial_info(port, argp);
@@ -1517,6 +1507,7 @@ static const struct tty_operations riscom_ops = {
.hangup = rc_hangup,
.tiocmget = rc_tiocmget,
.tiocmset = rc_tiocmset,
+ .break_ctl = rc_send_break,
};
static int __init rc_init_drivers(void)
@@ -1538,7 +1529,7 @@ static int __init rc_init_drivers(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
riscom_driver->init_termios.c_ispeed = 9600;
riscom_driver->init_termios.c_ospeed = 9600;
- riscom_driver->flags = TTY_DRIVER_REAL_RAW;
+ riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(riscom_driver, &riscom_ops);
error = tty_register_driver(riscom_driver);
if (error != 0) {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index e670eae2f51..584d791e84a 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty,
}
}
-static void rp_break(struct tty_struct *tty, int break_state)
+static int rp_break(struct tty_struct *tty, int break_state)
{
struct r_port *info = (struct r_port *) tty->driver_data;
unsigned long flags;
if (rocket_paranoia_check(info, "rp_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->slock, flags);
if (break_state == -1)
@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state)
else
sClrBreak(&info->channel);
spin_unlock_irqrestore(&info->slock, flags);
+ return 0;
}
/*
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index fa92a8af5a5..dbefbb30ed4 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -78,9 +78,10 @@
#include <linux/wait.h>
#include <linux/bcd.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
#include <asm/current.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#ifdef CONFIG_X86
@@ -120,8 +121,6 @@ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
return 0;
}
#endif
-#else
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
#endif
/*
@@ -144,8 +143,7 @@ static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
static ssize_t rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
-static int rtc_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#ifdef RTC_IRQ
static unsigned int rtc_poll(struct file *file, poll_table *wait);
@@ -719,10 +717,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
&wtime, sizeof wtime) ? -EFAULT : 0;
}
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return rtc_do_ioctl(cmd, arg, 0);
+ long ret;
+ lock_kernel();
+ ret = rtc_do_ioctl(cmd, arg, 0);
+ unlock_kernel();
+ return ret;
}
/*
@@ -915,7 +916,7 @@ static const struct file_operations rtc_fops = {
#ifdef RTC_IRQ
.poll = rtc_poll,
#endif
- .ioctl = rtc_ioctl,
+ .unlocked_ioctl = rtc_ioctl,
.open = rtc_open,
.release = rtc_release,
.fasync = rtc_fasync,
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 0b799ac1b04..3ce60df14c0 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -444,7 +444,8 @@ scdrv_init(void)
continue;
}
- device_create(snsc_class, NULL, dev, "%s", devname);
+ device_create_drvdata(snsc_class, NULL, dev, NULL,
+ "%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
0 /*ignored */ ,
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 037dc47e4cb..242fd46fda2 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -77,7 +77,7 @@
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ioport.h>
@@ -92,7 +92,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "specialix_io8.h"
#include "cd1865.h"
@@ -110,9 +110,10 @@
static int sx_debug;
static int sx_rxfifo = SPECIALIX_RXFIFO;
+static int sx_rtscts;
#ifdef DEBUG
-#define dprintk(f, str...) if (sx_debug & f) printk (str)
+#define dprintk(f, str...) if (sx_debug & f) printk(str)
#else
#define dprintk(f, str...) /* nothing */
#endif
@@ -131,10 +132,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
#define SX_DEBUG_FIFO 0x0800
-#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__)
-#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
-
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
+#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__)
/* Configurable options: */
@@ -142,17 +141,6 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
/* Am I paranoid or not ? ;-) */
#define SPECIALIX_PARANOIA_CHECK
-/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
- When the IRQ routine leaves the chip in a state that is keeps on
- requiring attention, the timer doesn't help either. */
-#undef SPECIALIX_TIMER
-
-#ifdef SPECIALIX_TIMER
-static int sx_poll = HZ;
-#endif
-
-
-
/*
* The following defines are mostly for testing purposes. But if you need
* some nice reporting in your syslog, you can define them also.
@@ -162,16 +150,6 @@ static int sx_poll = HZ;
-#ifdef CONFIG_SPECIALIX_RTSCTS
-#define SX_CRTSCTS(bla) 1
-#else
-#define SX_CRTSCTS(tty) C_CRTSCTS(tty)
-#endif
-
-
-/* Used to be outb (0xff, 0x80); */
-#define short_pause() udelay (1)
-
#define SPECIALIX_LEGAL_FLAGS \
(ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
@@ -190,21 +168,14 @@ static struct specialix_board sx_board[SX_NBOARD] = {
static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-#ifdef SPECIALIX_TIMER
-static struct timer_list missed_irq_timer;
-static irqreturn_t sx_interrupt(int irq, void * dev_id);
-#endif
-
-
-
-static inline int sx_paranoia_check(struct specialix_port const * port,
+static int sx_paranoia_check(struct specialix_port const *port,
char *name, const char *routine)
{
#ifdef SPECIALIX_PARANOIA_CHECK
- static const char *badmagic =
- KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
- static const char *badinfo =
- KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
+ static const char *badmagic = KERN_ERR
+ "sx: Warning: bad specialix port magic number for device %s in %s\n";
+ static const char *badinfo = KERN_ERR
+ "sx: Warning: null specialix port for device %s in %s\n";
if (!port) {
printk(badinfo, name, routine);
@@ -226,66 +197,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port,
*/
/* Get board number from pointer */
-static inline int board_No (struct specialix_board * bp)
+static inline int board_No(struct specialix_board *bp)
{
return bp - sx_board;
}
/* Get port number from pointer */
-static inline int port_No (struct specialix_port const * port)
+static inline int port_No(struct specialix_port const *port)
{
return SX_PORT(port - sx_port);
}
/* Get pointer to board from pointer to port */
-static inline struct specialix_board * port_Board(struct specialix_port const * port)
+static inline struct specialix_board *port_Board(
+ struct specialix_port const *port)
{
return &sx_board[SX_BOARD(port - sx_port)];
}
/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in(struct specialix_board *bp,
+ unsigned short reg)
{
bp->reg = reg | 0x80;
- outb (reg | 0x80, bp->base + SX_ADDR_REG);
- return inb (bp->base + SX_DATA_REG);
+ outb(reg | 0x80, bp->base + SX_ADDR_REG);
+ return inb(bp->base + SX_DATA_REG);
}
/* Output Byte to CL CD186x register */
-static inline void sx_out(struct specialix_board * bp, unsigned short reg,
+static inline void sx_out(struct specialix_board *bp, unsigned short reg,
unsigned char val)
{
bp->reg = reg | 0x80;
- outb (reg | 0x80, bp->base + SX_ADDR_REG);
- outb (val, bp->base + SX_DATA_REG);
+ outb(reg | 0x80, bp->base + SX_ADDR_REG);
+ outb(val, bp->base + SX_DATA_REG);
}
/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
+static inline unsigned char sx_in_off(struct specialix_board *bp,
+ unsigned short reg)
{
bp->reg = reg;
- outb (reg, bp->base + SX_ADDR_REG);
- return inb (bp->base + SX_DATA_REG);
+ outb(reg, bp->base + SX_ADDR_REG);
+ return inb(bp->base + SX_DATA_REG);
}
/* Output Byte to CL CD186x register */
-static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
- unsigned char val)
+static inline void sx_out_off(struct specialix_board *bp,
+ unsigned short reg, unsigned char val)
{
bp->reg = reg;
- outb (reg, bp->base + SX_ADDR_REG);
- outb (val, bp->base + SX_DATA_REG);
+ outb(reg, bp->base + SX_ADDR_REG);
+ outb(val, bp->base + SX_DATA_REG);
}
/* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR(struct specialix_board * bp)
+static void sx_wait_CCR(struct specialix_board *bp)
{
unsigned long delay, flags;
unsigned char ccr;
@@ -296,7 +270,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
spin_unlock_irqrestore(&bp->lock, flags);
if (!ccr)
return;
- udelay (1);
+ udelay(1);
}
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -304,7 +278,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
/* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR_off(struct specialix_board * bp)
+static void sx_wait_CCR_off(struct specialix_board *bp)
{
unsigned long delay;
unsigned char crr;
@@ -316,7 +290,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
spin_unlock_irqrestore(&bp->lock, flags);
if (!crr)
return;
- udelay (1);
+ udelay(1);
}
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -327,7 +301,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp)
* specialix IO8+ IO range functions.
*/
-static inline int sx_request_io_range(struct specialix_board * bp)
+static int sx_request_io_range(struct specialix_board *bp)
{
return request_region(bp->base,
bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
@@ -335,15 +309,15 @@ static inline int sx_request_io_range(struct specialix_board * bp)
}
-static inline void sx_release_io_range(struct specialix_board * bp)
+static void sx_release_io_range(struct specialix_board *bp)
{
- release_region(bp->base,
- bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
+ release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
+ SX_PCI_IO_SPACE : SX_IO_SPACE);
}
/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq ( struct specialix_board *bp)
+static int sx_set_irq(struct specialix_board *bp)
{
int virq;
int i;
@@ -353,15 +327,24 @@ static int sx_set_irq ( struct specialix_board *bp)
return 1;
switch (bp->irq) {
/* In the same order as in the docs... */
- case 15: virq = 0;break;
- case 12: virq = 1;break;
- case 11: virq = 2;break;
- case 9: virq = 3;break;
- default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
- return 0;
+ case 15:
+ virq = 0;
+ break;
+ case 12:
+ virq = 1;
+ break;
+ case 11:
+ virq = 2;
+ break;
+ case 9:
+ virq = 3;
+ break;
+ default:printk(KERN_ERR
+ "Speclialix: cannot set irq to %d.\n", bp->irq);
+ return 0;
}
spin_lock_irqsave(&bp->lock, flags);
- for (i=0;i<2;i++) {
+ for (i = 0; i < 2; i++) {
sx_out(bp, CD186x_CAR, i);
sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
}
@@ -371,7 +354,7 @@ static int sx_set_irq ( struct specialix_board *bp)
/* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board * bp)
+static int sx_init_CD186x(struct specialix_board *bp)
{
unsigned long flags;
int scaler;
@@ -390,7 +373,7 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
/* Set RegAckEn */
- sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
+ sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
/* Setting up prescaler. We need 4 ticks per 1 ms */
scaler = SX_OSCFREQ/SPECIALIX_TPS;
@@ -399,9 +382,9 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
- if (!sx_set_irq (bp)) {
+ if (!sx_set_irq(bp)) {
/* Figure out how to pass this along... */
- printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
+ printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
rv = 0;
}
@@ -410,16 +393,16 @@ static int sx_init_CD186x(struct specialix_board * bp)
}
-static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
+static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
{
int i;
int t;
unsigned long flags;
spin_lock_irqsave(&bp->lock, flags);
- for (i=0, t=0;i<8;i++) {
- sx_out_off (bp, CD186x_CAR, i);
- if (sx_in_off (bp, reg) & bit)
+ for (i = 0, t = 0; i < 8; i++) {
+ sx_out_off(bp, CD186x_CAR, i);
+ if (sx_in_off(bp, reg) & bit)
t |= 1 << i;
}
spin_unlock_irqrestore(&bp->lock, flags);
@@ -428,37 +411,10 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
}
-#ifdef SPECIALIX_TIMER
-void missed_irq (unsigned long data)
-{
- unsigned char irq;
- unsigned long flags;
- struct specialix_board *bp = (struct specialix_board *)data;
-
- spin_lock_irqsave(&bp->lock, flags);
- irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
- (SRSR_RREQint |
- SRSR_TREQint |
- SRSR_MREQint);
- spin_unlock_irqrestore(&bp->lock, flags);
- if (irq) {
- printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
- sx_interrupt (-1, bp);
- }
- mod_timer(&missed_irq_timer, jiffies + sx_poll);
-}
-#endif
-
-
-
/* Main probing routine, also sets irq. */
static int sx_probe(struct specialix_board *bp)
{
unsigned char val1, val2;
-#if 0
- int irqs = 0;
- int retries;
-#endif
int rev;
int chip;
@@ -471,17 +427,18 @@ static int sx_probe(struct specialix_board *bp)
/* Are the I/O ports here ? */
sx_out_off(bp, CD186x_PPRL, 0x5a);
- short_pause ();
+ udelay(1);
val1 = sx_in_off(bp, CD186x_PPRL);
sx_out_off(bp, CD186x_PPRL, 0xa5);
- short_pause ();
+ udelay(1);
val2 = sx_in_off(bp, CD186x_PPRL);
- if ((val1 != 0x5a) || (val2 != 0xa5)) {
- printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
- board_No(bp), bp->base);
+ if (val1 != 0x5a || val2 != 0xa5) {
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
+ board_No(bp), bp->base);
sx_release_io_range(bp);
func_exit();
return 1;
@@ -489,10 +446,11 @@ static int sx_probe(struct specialix_board *bp)
/* Check the DSR lines that Specialix uses as board
identification */
- val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
- val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
- dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
- board_No(bp), val1, val2);
+ val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
+ val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
+ dprintk(SX_DEBUG_INIT,
+ "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
+ board_No(bp), val1, val2);
/* They managed to switch the bit order between the docs and
the IO8+ card. The new PCI card now conforms to old docs.
@@ -500,7 +458,8 @@ static int sx_probe(struct specialix_board *bp)
old card. */
val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
if (val1 != val2) {
- printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
board_No(bp), val2, bp->base, val1);
sx_release_io_range(bp);
func_exit();
@@ -508,47 +467,6 @@ static int sx_probe(struct specialix_board *bp)
}
-#if 0
- /* It's time to find IRQ for this board */
- for (retries = 0; retries < 5 && irqs <= 0; retries++) {
- irqs = probe_irq_on();
- sx_init_CD186x(bp); /* Reset CD186x chip */
- sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
- sx_wait_CCR(bp);
- sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
- sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
- msleep(50);
- irqs = probe_irq_off(irqs);
-
- dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
- dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
- dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
- dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
- dprintk (SX_DEBUG_INIT, "\n");
-
- /* Reset CD186x again */
- if (!sx_init_CD186x(bp)) {
- /* Hmmm. This is dead code anyway. */
- }
-
- dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
- val1, val2, val3);
-
- }
-
-#if 0
- if (irqs <= 0) {
- printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
- board_No(bp), bp->base);
- sx_release_io_range(bp);
- func_exit();
- return 1;
- }
-#endif
- printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
- if (irqs > 0)
- bp->irq = irqs;
-#endif
/* Reset CD186x again */
if (!sx_init_CD186x(bp)) {
sx_release_io_range(bp);
@@ -560,7 +478,7 @@ static int sx_probe(struct specialix_board *bp)
bp->flags |= SX_BOARD_PRESENT;
/* Chip revcode pkgtype
- GFRCR SRCR bit 7
+ GFRCR SRCR bit 7
CD180 rev B 0x81 0
CD180 rev C 0x82 0
CD1864 rev A 0x82 1
@@ -570,24 +488,32 @@ static int sx_probe(struct specialix_board *bp)
*/
switch (sx_in_off(bp, CD186x_GFRCR)) {
- case 0x82:chip = 1864;rev='A';break;
- case 0x83:chip = 1865;rev='A';break;
- case 0x84:chip = 1865;rev='B';break;
- case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
- default:chip=-1;rev='x';
+ case 0x82:
+ chip = 1864;
+ rev = 'A';
+ break;
+ case 0x83:
+ chip = 1865;
+ rev = 'A';
+ break;
+ case 0x84:
+ chip = 1865;
+ rev = 'B';
+ break;
+ case 0x85:
+ chip = 1865;
+ rev = 'C';
+ break; /* Does not exist at this time */
+ default:
+ chip = -1;
+ rev = 'x';
}
- dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
-
-#ifdef SPECIALIX_TIMER
- setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
- mod_timer(&missed_irq_timer, jiffies + sx_poll);
-#endif
+ dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
- printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
- board_No(bp),
- bp->base, bp->irq,
- chip, rev);
+ printk(KERN_INFO
+ "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
+ board_No(bp), bp->base, bp->irq, chip, rev);
func_exit();
return 0;
@@ -598,20 +524,22 @@ static int sx_probe(struct specialix_board *bp)
* Interrupt processing routines.
* */
-static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
- unsigned char const * what)
+static struct specialix_port *sx_get_port(struct specialix_board *bp,
+ unsigned char const *what)
{
unsigned char channel;
- struct specialix_port * port = NULL;
+ struct specialix_port *port = NULL;
channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
- dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
+ dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
if (channel < CD186x_NCH) {
port = &sx_port[board_No(bp) * SX_NPORT + channel];
- dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel, port, port->port.flags & ASYNC_INITIALIZED);
+ dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
+ board_No(bp) * SX_NPORT + channel, port,
+ port->port.flags & ASYNC_INITIALIZED);
if (port->port.flags & ASYNC_INITIALIZED) {
- dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
+ dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
func_exit();
return port;
}
@@ -622,7 +550,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
}
-static inline void sx_receive_exc(struct specialix_board * bp)
+static void sx_receive_exc(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -633,7 +561,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
port = sx_get_port(bp, "Receive");
if (!port) {
- dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
func_exit();
return;
}
@@ -641,19 +569,21 @@ static inline void sx_receive_exc(struct specialix_board * bp)
status = sx_in(bp, CD186x_RCSR);
- dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
+ dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
if (status & RCSR_OE) {
port->overrun++;
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
- board_No(bp), port_No(port), port->overrun);
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: Overrun. Total %ld overruns.\n",
+ board_No(bp), port_No(port), port->overrun);
}
status &= port->mark_mask;
/* This flip buffer check needs to be below the reading of the
status register to reset the chip's IRQ.... */
if (tty_buffer_request_room(tty, 1) == 0) {
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
- board_No(bp), port_No(port));
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: Working around flip buffer overflow.\n",
+ board_No(bp), port_No(port));
func_exit();
return;
}
@@ -664,8 +594,9 @@ static inline void sx_receive_exc(struct specialix_board * bp)
return;
}
if (status & RCSR_TOUT) {
- printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
- board_No(bp), port_No(port));
+ printk(KERN_INFO
+ "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
+ board_No(bp), port_No(port));
func_exit();
return;
@@ -688,13 +619,13 @@ static inline void sx_receive_exc(struct specialix_board * bp)
else
flag = TTY_NORMAL;
- if(tty_insert_flip_char(tty, ch, flag))
+ if (tty_insert_flip_char(tty, ch, flag))
tty_flip_buffer_push(tty);
func_exit();
}
-static inline void sx_receive(struct specialix_board * bp)
+static void sx_receive(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
@@ -702,15 +633,16 @@ static inline void sx_receive(struct specialix_board * bp)
func_enter();
- if (!(port = sx_get_port(bp, "Receive"))) {
- dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ port = sx_get_port(bp, "Receive");
+ if (port == NULL) {
+ dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
func_exit();
return;
}
tty = port->port.tty;
count = sx_in(bp, CD186x_RDCR);
- dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
+ dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
port->hits[count > 8 ? 9 : count]++;
tty_buffer_request_room(tty, count);
@@ -722,18 +654,19 @@ static inline void sx_receive(struct specialix_board * bp)
}
-static inline void sx_transmit(struct specialix_board * bp)
+static void sx_transmit(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
unsigned char count;
func_enter();
- if (!(port = sx_get_port(bp, "Transmit"))) {
+ port = sx_get_port(bp, "Transmit");
+ if (port == NULL) {
func_exit();
return;
}
- dprintk (SX_DEBUG_TX, "port: %p\n", port);
+ dprintk(SX_DEBUG_TX, "port: %p\n", port);
tty = port->port.tty;
if (port->IER & IER_TXEMPTY) {
@@ -765,7 +698,8 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_TDR, CD186x_C_ESC);
sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
sx_out(bp, CD186x_TDR, count);
- if (!(port->break_length -= count))
+ port->break_length -= count;
+ if (port->break_length == 0)
port->break_length--;
} else {
sx_out(bp, CD186x_TDR, CD186x_C_ESC);
@@ -794,36 +728,36 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_IER, port->IER);
}
if (port->xmit_cnt <= port->wakeup_chars)
- tty_wakeup(tty);
+ tty_wakeup(tty);
func_exit();
}
-static inline void sx_check_modem(struct specialix_board * bp)
+static void sx_check_modem(struct specialix_board *bp)
{
struct specialix_port *port;
struct tty_struct *tty;
unsigned char mcr;
int msvr_cd;
- dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
- if (!(port = sx_get_port(bp, "Modem")))
+ dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
+ port = sx_get_port(bp, "Modem");
+ if (port == NULL)
return;
tty = port->port.tty;
mcr = sx_in(bp, CD186x_MCR);
- printk ("mcr = %02x.\n", mcr);
if ((mcr & MCR_CDCHG)) {
- dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
+ dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
if (msvr_cd) {
- dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
+ dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
wake_up_interruptible(&port->port.open_wait);
} else {
- dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
+ dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
tty_hangup(tty);
}
}
@@ -874,9 +808,12 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
spin_lock_irqsave(&bp->lock, flags);
- dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+ dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
+ port_No(sx_get_port(bp, "INT")),
+ SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
if (!(bp->flags & SX_BOARD_ACTIVE)) {
- dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
+ dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
+ bp->irq);
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
return IRQ_NONE;
@@ -884,10 +821,11 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
saved_reg = bp->reg;
- while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
- (SRSR_RREQint |
- SRSR_TREQint |
- SRSR_MREQint)))) {
+ while (++loop < 16) {
+ status = sx_in(bp, CD186x_SRSR) &
+ (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
+ if (status == 0)
+ break;
if (status & SRSR_RREQint) {
ack = sx_in(bp, CD186x_RRAR);
@@ -896,8 +834,9 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
else if (ack == (SX_ID | GIVR_IT_REXC))
sx_receive_exc(bp);
else
- printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
- board_No(bp), status, ack);
+ printk(KERN_ERR
+ "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
+ board_No(bp), status, ack);
} else if (status & SRSR_TREQint) {
ack = sx_in(bp, CD186x_TRAR);
@@ -906,14 +845,16 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
sx_transmit(bp);
else
printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
- board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
+ board_No(bp), status, ack,
+ port_No(sx_get_port(bp, "Int")));
} else if (status & SRSR_MREQint) {
ack = sx_in(bp, CD186x_MRAR);
if (ack == (SX_ID | GIVR_IT_MODEM))
sx_check_modem(bp);
else
- printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
+ printk(KERN_ERR
+ "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
board_No(bp), status, ack);
}
@@ -921,7 +862,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
}
bp->reg = saved_reg;
- outb (bp->reg, bp->base + SX_ADDR_REG);
+ outb(bp->reg, bp->base + SX_ADDR_REG);
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
return IRQ_HANDLED;
@@ -932,36 +873,26 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
* Routines for open & close processing.
*/
-static void turn_ints_off (struct specialix_board *bp)
+static void turn_ints_off(struct specialix_board *bp)
{
unsigned long flags;
func_enter();
- if (bp->flags & SX_BOARD_IS_PCI) {
- /* This was intended for enabeling the interrupt on the
- * PCI card. However it seems that it's already enabled
- * and as PCI interrupts can be shared, there is no real
- * reason to have to turn it off. */
- }
-
spin_lock_irqsave(&bp->lock, flags);
- (void) sx_in_off (bp, 0); /* Turn off interrupts. */
+ (void) sx_in_off(bp, 0); /* Turn off interrupts. */
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
}
-static void turn_ints_on (struct specialix_board *bp)
+static void turn_ints_on(struct specialix_board *bp)
{
unsigned long flags;
func_enter();
- if (bp->flags & SX_BOARD_IS_PCI) {
- /* play with the PCI chip. See comment above. */
- }
spin_lock_irqsave(&bp->lock, flags);
- (void) sx_in (bp, 0); /* Turn ON interrupts. */
+ (void) sx_in(bp, 0); /* Turn ON interrupts. */
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
@@ -969,7 +900,7 @@ static void turn_ints_on (struct specialix_board *bp)
/* Called with disabled interrupts */
-static inline int sx_setup_board(struct specialix_board * bp)
+static int sx_setup_board(struct specialix_board *bp)
{
int error;
@@ -977,14 +908,16 @@ static inline int sx_setup_board(struct specialix_board * bp)
return 0;
if (bp->flags & SX_BOARD_IS_PCI)
- error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt,
+ IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
else
- error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt,
+ IRQF_DISABLED, "specialix IO8+", bp);
if (error)
return error;
- turn_ints_on (bp);
+ turn_ints_on(bp);
bp->flags |= SX_BOARD_ACTIVE;
return 0;
@@ -992,7 +925,7 @@ static inline int sx_setup_board(struct specialix_board * bp)
/* Called with disabled interrupts */
-static inline void sx_shutdown_board(struct specialix_board *bp)
+static void sx_shutdown_board(struct specialix_board *bp)
{
func_enter();
@@ -1003,22 +936,26 @@ static inline void sx_shutdown_board(struct specialix_board *bp)
bp->flags &= ~SX_BOARD_ACTIVE;
- dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
- bp->irq, board_No (bp));
+ dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
+ bp->irq, board_No(bp));
free_irq(bp->irq, bp);
-
- turn_ints_off (bp);
-
-
+ turn_ints_off(bp);
func_exit();
}
+static unsigned int sx_crtscts(struct tty_struct *tty)
+{
+ if (sx_rtscts)
+ return C_CRTSCTS(tty);
+ return 1;
+}
/*
* Setting up port characteristics.
* Must be called with disabled interrupts
*/
-static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
+static void sx_change_speed(struct specialix_board *bp,
+ struct specialix_port *port)
{
struct tty_struct *tty;
unsigned long baud;
@@ -1030,7 +967,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
func_enter();
- if (!(tty = port->port.tty) || !tty->termios) {
+ tty = port->port.tty;
+ if (!tty || !tty->termios) {
func_exit();
return;
}
@@ -1043,12 +981,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* The Specialix board doens't implement the RTS lines.
They are used to set the IRQ level. Don't touch them. */
- if (SX_CRTSCTS(tty))
+ if (sx_crtscts(tty))
port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
else
port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
spin_unlock_irqrestore(&bp->lock, flags);
- dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
+ dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
baud = tty_get_baud_rate(tty);
if (baud == 38400) {
@@ -1060,21 +998,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
if (!baud) {
/* Drop DTR & exit */
- dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
- if (!SX_CRTSCTS (tty)) {
- port -> MSVR &= ~ MSVR_DTR;
+ dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
+ if (!sx_crtscts(tty)) {
+ port->MSVR &= ~MSVR_DTR;
spin_lock_irqsave(&bp->lock, flags);
- sx_out(bp, CD186x_MSVR, port->MSVR );
+ sx_out(bp, CD186x_MSVR, port->MSVR);
spin_unlock_irqrestore(&bp->lock, flags);
- }
- else
- dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
+ } else
+ dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
return;
} else {
/* Set DTR on */
- if (!SX_CRTSCTS (tty)) {
- port ->MSVR |= MSVR_DTR;
- }
+ if (!sx_crtscts(tty))
+ port->MSVR |= MSVR_DTR;
}
/*
@@ -1083,28 +1019,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Set baud rate for port */
tmp = port->custom_divisor ;
- if ( tmp )
- printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
- "This is an untested option, please be carefull.\n",
- port_No (port), tmp);
+ if (tmp)
+ printk(KERN_INFO
+ "sx%d: Using custom baud rate divisor %ld. \n"
+ "This is an untested option, please be careful.\n",
+ port_No(port), tmp);
else
- tmp = (((SX_OSCFREQ + baud/2) / baud +
- CD186x_TPC/2) / CD186x_TPC);
+ tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
+ CD186x_TPC);
- if ((tmp < 0x10) && time_before(again, jiffies)) {
+ if (tmp < 0x10 && time_before(again, jiffies)) {
again = jiffies + HZ * 60;
/* Page 48 of version 2.0 of the CL-CD1865 databook */
if (tmp >= 12) {
- printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
- "Performance degradation is possible.\n"
- "Read specialix.txt for more info.\n",
- port_No (port), tmp);
+ printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+ "Performance degradation is possible.\n"
+ "Read specialix.txt for more info.\n",
+ port_No(port), tmp);
} else {
- printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
- "Warning: overstressing Cirrus chip. "
- "This might not work.\n"
- "Read specialix.txt for more info.\n",
- port_No (port), tmp);
+ printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+ "Warning: overstressing Cirrus chip. This might not work.\n"
+ "Read specialix.txt for more info.\n", port_No(port), tmp);
}
}
spin_lock_irqsave(&bp->lock, flags);
@@ -1114,7 +1049,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
sx_out(bp, CD186x_TBPRL, tmp & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
if (port->custom_divisor)
- baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
+ baud = (SX_OSCFREQ + port->custom_divisor/2) /
+ port->custom_divisor;
baud = (baud + 5) / 10; /* Estimated CPS */
/* Two timer ticks seems enough to wakeup something like SLIP driver */
@@ -1129,16 +1065,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
sx_out(bp, CD186x_RTPR, tmp);
spin_unlock_irqrestore(&bp->lock, flags);
switch (C_CSIZE(tty)) {
- case CS5:
+ case CS5:
cor1 |= COR1_5BITS;
break;
- case CS6:
+ case CS6:
cor1 |= COR1_6BITS;
break;
- case CS7:
+ case CS7:
cor1 |= COR1_7BITS;
break;
- case CS8:
+ case CS8:
cor1 |= COR1_8BITS;
break;
}
@@ -1175,7 +1111,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
spin_lock_irqsave(&bp->lock, flags);
- tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
+ tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
+ (MSVR_CTS|MSVR_DSR));
spin_unlock_irqrestore(&bp->lock, flags);
#else
port->COR2 |= COR2_CTSAE;
@@ -1219,7 +1156,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
/* Setting up modem option registers */
- dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
+ dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
+ mcor1, mcor2);
sx_out(bp, CD186x_MCOR1, mcor1);
sx_out(bp, CD186x_MCOR2, mcor2);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1238,7 +1176,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
+static int sx_setup_port(struct specialix_board *bp,
+ struct specialix_port *port)
{
unsigned long flags;
@@ -1253,7 +1192,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
/* We may sleep in get_zeroed_page() */
unsigned long tmp;
- if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
+ tmp = get_zeroed_page(GFP_KERNEL);
+ if (tmp == 0L) {
func_exit();
return -ENOMEM;
}
@@ -1284,7 +1224,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
/* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
+static void sx_shutdown_port(struct specialix_board *bp,
+ struct specialix_port *port)
{
struct tty_struct *tty;
int i;
@@ -1298,11 +1239,11 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
}
if (sx_debug & SX_DEBUG_FIFO) {
- dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
- board_No(bp), port_No(port), port->overrun);
- for (i = 0; i < 10; i++) {
+ dprintk(SX_DEBUG_FIFO,
+ "sx%d: port %d: %ld overruns, FIFO hits [ ",
+ board_No(bp), port_No(port), port->overrun);
+ for (i = 0; i < 10; i++)
dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
- }
dprintk(SX_DEBUG_FIFO, "].\n");
}
@@ -1315,7 +1256,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
- if (!(tty = port->port.tty) || C_HUPCL(tty)) {
+ tty = port->port.tty;
+ if (tty == NULL || C_HUPCL(tty)) {
/* Drop DTR */
sx_out(bp, CD186x_MSVDTR, 0);
}
@@ -1338,8 +1280,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *
}
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct specialix_port *port)
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct specialix_port *port)
{
DECLARE_WAITQUEUE(wait, current);
struct specialix_board *bp = port_Board(port);
@@ -1389,23 +1331,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
retval = 0;
add_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
- if (!tty_hung_up_p(filp)) {
+ if (!tty_hung_up_p(filp))
port->port.count--;
- }
spin_unlock_irqrestore(&port->lock, flags);
port->port.blocked_open++;
while (1) {
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
- if (SX_CRTSCTS (tty)) {
+ if (sx_crtscts(tty)) {
/* Activate RTS */
port->MSVR |= MSVR_DTR; /* WTF? */
- sx_out (bp, CD186x_MSVR, port->MSVR);
+ sx_out(bp, CD186x_MSVR, port->MSVR);
} else {
/* Activate DTR */
port->MSVR |= MSVR_DTR;
- sx_out (bp, CD186x_MSVR, port->MSVR);
+ sx_out(bp, CD186x_MSVR, port->MSVR);
}
spin_unlock_irqrestore(&bp->lock, flags);
set_current_state(TASK_INTERRUPTIBLE);
@@ -1430,9 +1371,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->port.open_wait, &wait);
spin_lock_irqsave(&port->lock, flags);
- if (!tty_hung_up_p(filp)) {
+ if (!tty_hung_up_p(filp))
port->port.count++;
- }
port->port.blocked_open--;
spin_unlock_irqrestore(&port->lock, flags);
if (retval) {
@@ -1446,12 +1386,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
}
-static int sx_open(struct tty_struct * tty, struct file * filp)
+static int sx_open(struct tty_struct *tty, struct file *filp)
{
int board;
int error;
- struct specialix_port * port;
- struct specialix_board * bp;
+ struct specialix_port *port;
+ struct specialix_board *bp;
int i;
unsigned long flags;
@@ -1468,17 +1408,19 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
port->overrun = 0;
for (i = 0; i < 10; i++)
- port->hits[i]=0;
+ port->hits[i] = 0;
- dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
- board, bp, port, SX_PORT(tty->index));
+ dprintk(SX_DEBUG_OPEN,
+ "Board = %d, bp = %p, port = %p, portno = %d.\n",
+ board, bp, port, SX_PORT(tty->index));
if (sx_paranoia_check(port, tty->name, "sx_open")) {
func_enter();
return -ENODEV;
}
- if ((error = sx_setup_board(bp))) {
+ error = sx_setup_board(bp);
+ if (error) {
func_exit();
return error;
}
@@ -1490,12 +1432,14 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
port->port.tty = tty;
spin_unlock_irqrestore(&bp->lock, flags);
- if ((error = sx_setup_port(bp, port))) {
+ error = sx_setup_port(bp, port);
+ if (error) {
func_enter();
return error;
}
- if ((error = block_til_ready(tty, filp, port))) {
+ error = block_til_ready(tty, filp, port);
+ if (error) {
func_enter();
return error;
}
@@ -1508,7 +1452,7 @@ static void sx_flush_buffer(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
func_enter();
@@ -1526,9 +1470,9 @@ static void sx_flush_buffer(struct tty_struct *tty)
func_exit();
}
-static void sx_close(struct tty_struct * tty, struct file * filp)
+static void sx_close(struct tty_struct *tty, struct file *filp)
{
- struct specialix_port *port = (struct specialix_port *) tty->driver_data;
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
unsigned long timeout;
@@ -1547,7 +1491,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
bp = port_Board(port);
- if ((tty->count == 1) && (port->port.count != 1)) {
+ if (tty->count == 1 && port->port.count != 1) {
printk(KERN_ERR "sx%d: sx_close: bad port count;"
" tty->count is 1, port count is %d\n",
board_No(bp), port->port.count);
@@ -1570,17 +1514,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
*/
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
- dprintk (SX_DEBUG_OPEN, "Closing\n");
- if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+ dprintk(SX_DEBUG_OPEN, "Closing\n");
+ if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->port.closing_wait);
- }
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
- dprintk (SX_DEBUG_OPEN, "Closed\n");
+ dprintk(SX_DEBUG_OPEN, "Closed\n");
port->IER &= ~IER_RXD;
if (port->port.flags & ASYNC_INITIALIZED) {
port->IER &= ~IER_TXRDY;
@@ -1595,11 +1538,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
* important if there is a transmit FIFO!
*/
timeout = jiffies+HZ;
- while(port->IER & IER_TXEMPTY) {
- set_current_state (TASK_INTERRUPTIBLE);
+ while (port->IER & IER_TXEMPTY) {
+ set_current_state(TASK_INTERRUPTIBLE);
msleep_interruptible(jiffies_to_msecs(port->timeout));
if (time_after(jiffies, timeout)) {
- printk (KERN_INFO "Timeout waiting for close\n");
+ printk(KERN_INFO "Timeout waiting for close\n");
break;
}
}
@@ -1607,13 +1550,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
if (--bp->count < 0) {
- printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
- board_No(bp), bp->count, tty->index);
+ printk(KERN_ERR
+ "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
bp->count = 0;
}
if (--port->port.count < 0) {
- printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
- board_No(bp), port_No(port), port->port.count);
+ printk(KERN_ERR
+ "sx%d: sx_close: bad port count for tty%d: %d\n",
+ board_No(bp), port_No(port), port->port.count);
port->port.count = 0;
}
@@ -1625,9 +1570,9 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
port->port.tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
if (port->port.blocked_open) {
- if (port->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(port->port.close_delay));
- }
+ if (port->port.close_delay)
+ msleep_interruptible(
+ jiffies_to_msecs(port->port.close_delay));
wake_up_interruptible(&port->port.open_wait);
}
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1637,8 +1582,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
-static int sx_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
+static int sx_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -1690,11 +1635,11 @@ static int sx_write(struct tty_struct * tty,
}
-static int sx_put_char(struct tty_struct * tty, unsigned char ch)
+static int sx_put_char(struct tty_struct *tty, unsigned char ch)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
func_enter();
@@ -1702,7 +1647,7 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
func_exit();
return 0;
}
- dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+ dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
if (!port->xmit_buf) {
func_exit();
return 0;
@@ -1710,14 +1655,15 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
bp = port_Board(port);
spin_lock_irqsave(&port->lock, flags);
- dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
- if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
+ dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
+ port->xmit_cnt, port->xmit_buf);
+ if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
spin_unlock_irqrestore(&port->lock, flags);
- dprintk (SX_DEBUG_TX, "Exit size\n");
+ dprintk(SX_DEBUG_TX, "Exit size\n");
func_exit();
return 0;
}
- dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
+ dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++;
@@ -1728,11 +1674,11 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch)
}
-static void sx_flush_chars(struct tty_struct * tty)
+static void sx_flush_chars(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp = port_Board(port);
+ struct specialix_board *bp = port_Board(port);
func_enter();
@@ -1755,7 +1701,7 @@ static void sx_flush_chars(struct tty_struct * tty)
}
-static int sx_write_room(struct tty_struct * tty)
+static int sx_write_room(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
int ret;
@@ -1790,12 +1736,10 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
return port->xmit_cnt;
}
-
-
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
- struct specialix_board * bp;
+ struct specialix_board *bp;
unsigned char status;
unsigned int result;
unsigned long flags;
@@ -1808,25 +1752,23 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
}
bp = port_Board(port);
- spin_lock_irqsave (&bp->lock, flags);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
status = sx_in(bp, CD186x_MSVR);
spin_unlock_irqrestore(&bp->lock, flags);
- dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
- port_No(port), status, sx_in (bp, CD186x_CAR));
- dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
- if (SX_CRTSCTS(port->port.tty)) {
- result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
- | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
- | ((status & MSVR_CD) ? TIOCM_CAR : 0)
- |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
- | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+ dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
+ port_No(port), status, sx_in(bp, CD186x_CAR));
+ dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
+ if (sx_crtscts(port->port.tty)) {
+ result = TIOCM_DTR | TIOCM_DSR
+ | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
+ | ((status & MSVR_CD) ? TIOCM_CAR : 0)
+ | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
} else {
- result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
- | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
- | ((status & MSVR_CD) ? TIOCM_CAR : 0)
- |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
- | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+ result = TIOCM_RTS | TIOCM_DSR
+ | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
+ | ((status & MSVR_CD) ? TIOCM_CAR : 0)
+ | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
}
func_exit();
@@ -1852,24 +1794,14 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
bp = port_Board(port);
spin_lock_irqsave(&port->lock, flags);
- /* if (set & TIOCM_RTS)
- port->MSVR |= MSVR_RTS; */
- /* if (set & TIOCM_DTR)
- port->MSVR |= MSVR_DTR; */
-
- if (SX_CRTSCTS(port->port.tty)) {
+ if (sx_crtscts(port->port.tty)) {
if (set & TIOCM_RTS)
port->MSVR |= MSVR_DTR;
} else {
if (set & TIOCM_DTR)
port->MSVR |= MSVR_DTR;
}
-
- /* if (clear & TIOCM_RTS)
- port->MSVR &= ~MSVR_RTS; */
- /* if (clear & TIOCM_DTR)
- port->MSVR &= ~MSVR_DTR; */
- if (SX_CRTSCTS(port->port.tty)) {
+ if (sx_crtscts(port->port.tty)) {
if (clear & TIOCM_RTS)
port->MSVR &= ~MSVR_DTR;
} else {
@@ -1886,14 +1818,17 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
}
-static inline void sx_send_break(struct specialix_port * port, unsigned long length)
+static int sx_send_break(struct tty_struct *tty, int length)
{
+ struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp = port_Board(port);
unsigned long flags;
func_enter();
+ if (length == 0 || length == -1)
+ return -EOPNOTSUPP;
- spin_lock_irqsave (&port->lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
port->break_length = SPECIALIX_TPS / HZ * length;
port->COR2 |= COR2_ETC;
port->IER |= IER_TXRDY;
@@ -1902,7 +1837,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
sx_out(bp, CD186x_COR2, port->COR2);
sx_out(bp, CD186x_IER, port->IER);
spin_unlock_irqrestore(&bp->lock, flags);
- spin_unlock_irqrestore (&port->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
sx_wait_CCR(bp);
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG2);
@@ -1910,11 +1845,12 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
sx_wait_CCR(bp);
func_exit();
+ return 0;
}
-static inline int sx_set_serial_info(struct specialix_port * port,
- struct serial_struct __user * newinfo)
+static int sx_set_serial_info(struct specialix_port *port,
+ struct serial_struct __user *newinfo)
{
struct serial_struct tmp;
struct specialix_board *bp = port_Board(port);
@@ -1943,25 +1879,25 @@ static inline int sx_set_serial_info(struct specialix_port * port,
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
- (tmp.flags & ASYNC_USR_MASK));
+ (tmp.flags & ASYNC_USR_MASK));
port->custom_divisor = tmp.custom_divisor;
} else {
port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
- (tmp.flags & ASYNC_FLAGS));
+ (tmp.flags & ASYNC_FLAGS));
port->port.close_delay = tmp.close_delay;
port->port.closing_wait = tmp.closing_wait;
port->custom_divisor = tmp.custom_divisor;
}
- if (change_speed) {
+ if (change_speed)
sx_change_speed(bp, port);
- }
+
func_exit();
unlock_kernel();
return 0;
}
-static inline int sx_get_serial_info(struct specialix_port * port,
+static int sx_get_serial_info(struct specialix_port *port,
struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
@@ -1992,11 +1928,10 @@ static inline int sx_get_serial_info(struct specialix_port * port,
}
-static int sx_ioctl(struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
- int retval;
void __user *argp = (void __user *)arg;
func_enter();
@@ -2007,34 +1942,14 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
}
switch (cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if (retval) {
- func_exit();
- return retval;
- }
- tty_wait_until_sent(tty, 0);
- if (!arg)
- sx_send_break(port, HZ/4); /* 1/4 second */
- return 0;
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if (retval) {
- func_exit();
- return retval;
- }
- tty_wait_until_sent(tty, 0);
- sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+ case TIOCGSERIAL:
func_exit();
- return 0;
- case TIOCGSERIAL:
- func_exit();
return sx_get_serial_info(port, argp);
- case TIOCSSERIAL:
- func_exit();
+ case TIOCSSERIAL:
+ func_exit();
return sx_set_serial_info(port, argp);
- default:
- func_exit();
+ default:
+ func_exit();
return -ENOIOCTLCMD;
}
func_exit();
@@ -2042,7 +1957,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
}
-static void sx_throttle(struct tty_struct * tty)
+static void sx_throttle(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2058,15 +1973,16 @@ static void sx_throttle(struct tty_struct * tty)
bp = port_Board(port);
/* Use DTR instead of RTS ! */
- if (SX_CRTSCTS (tty))
+ if (sx_crtscts(tty))
port->MSVR &= ~MSVR_DTR;
else {
/* Auch!!! I think the system shouldn't call this then. */
/* Or maybe we're supposed (allowed?) to do our side of hw
handshake anyway, even when hardware handshake is off.
When you see this in your logs, please report.... */
- printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
- port_No (port));
+ printk(KERN_ERR
+ "sx%d: Need to throttle, but can't (hardware hs is off)\n",
+ port_No(port));
}
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
@@ -2086,7 +2002,7 @@ static void sx_throttle(struct tty_struct * tty)
}
-static void sx_unthrottle(struct tty_struct * tty)
+static void sx_unthrottle(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2103,9 +2019,9 @@ static void sx_unthrottle(struct tty_struct * tty)
spin_lock_irqsave(&port->lock, flags);
/* XXXX Use DTR INSTEAD???? */
- if (SX_CRTSCTS(tty)) {
+ if (sx_crtscts(tty))
port->MSVR |= MSVR_DTR;
- } /* Else clause: see remark in "sx_throttle"... */
+ /* Else clause: see remark in "sx_throttle"... */
spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
spin_unlock_irqrestore(&bp->lock, flags);
@@ -2127,7 +2043,7 @@ static void sx_unthrottle(struct tty_struct * tty)
}
-static void sx_stop(struct tty_struct * tty)
+static void sx_stop(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2154,7 +2070,7 @@ static void sx_stop(struct tty_struct * tty)
}
-static void sx_start(struct tty_struct * tty)
+static void sx_start(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2182,7 +2098,7 @@ static void sx_start(struct tty_struct * tty)
func_exit();
}
-static void sx_hangup(struct tty_struct * tty)
+static void sx_hangup(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
@@ -2201,8 +2117,9 @@ static void sx_hangup(struct tty_struct * tty)
spin_lock_irqsave(&port->lock, flags);
bp->count -= port->port.count;
if (bp->count < 0) {
- printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
- board_No(bp), bp->count, tty->index);
+ printk(KERN_ERR
+ "sx%d: sx_hangup: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
bp->count = 0;
}
port->port.count = 0;
@@ -2215,11 +2132,12 @@ static void sx_hangup(struct tty_struct * tty)
}
-static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
+static void sx_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
- struct specialix_board * bp;
+ struct specialix_board *bp;
if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
return;
@@ -2254,6 +2172,7 @@ static const struct tty_operations sx_ops = {
.hangup = sx_hangup,
.tiocmget = sx_tiocmget,
.tiocmset = sx_tiocmset,
+ .break_ctl = sx_send_break,
};
static int sx_init_drivers(void)
@@ -2280,13 +2199,16 @@ static int sx_init_drivers(void)
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
specialix_driver->init_termios.c_ispeed = 9600;
specialix_driver->init_termios.c_ospeed = 9600;
- specialix_driver->flags = TTY_DRIVER_REAL_RAW;
+ specialix_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_HARDWARE_BREAK;
tty_set_operations(specialix_driver, &sx_ops);
- if ((error = tty_register_driver(specialix_driver))) {
+ error = tty_register_driver(specialix_driver);
+ if (error) {
put_tty_driver(specialix_driver);
- printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
- error);
+ printk(KERN_ERR
+ "sx: Couldn't register specialix IO8+ driver, error = %d\n",
+ error);
func_exit();
return 1;
}
@@ -2322,11 +2244,11 @@ static int __init specialix_init(void)
printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
-#ifdef CONFIG_SPECIALIX_RTSCTS
- printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
-#else
- printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
-#endif
+ if (sx_rtscts)
+ printk(KERN_INFO
+ "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
+ else
+ printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
for (i = 0; i < SX_NBOARD; i++)
spin_lock_init(&sx_board[i].lock);
@@ -2344,27 +2266,27 @@ static int __init specialix_init(void)
{
struct pci_dev *pdev = NULL;
- i=0;
+ i = 0;
while (i < SX_NBOARD) {
if (sx_board[i].flags & SX_BOARD_PRESENT) {
i++;
continue;
}
- pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_IO8,
- pdev);
- if (!pdev) break;
+ pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
+ PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
+ if (!pdev)
+ break;
if (pci_enable_device(pdev))
continue;
sx_board[i].irq = pdev->irq;
- sx_board[i].base = pci_resource_start (pdev, 2);
+ sx_board[i].base = pci_resource_start(pdev, 2);
sx_board[i].flags |= SX_BOARD_IS_PCI;
if (!sx_probe(&sx_board[i]))
- found ++;
+ found++;
}
/* May exit pci_get sequence early with lots of boards */
if (pdev != NULL)
@@ -2384,16 +2306,13 @@ static int __init specialix_init(void)
}
static int iobase[SX_NBOARD] = {0,};
-
-static int irq [SX_NBOARD] = {0,};
+static int irq[SX_NBOARD] = {0,};
module_param_array(iobase, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
module_param(sx_debug, int, 0);
+module_param(sx_rtscts, int, 0);
module_param(sx_rxfifo, int, 0);
-#ifdef SPECIALIX_TIMER
-module_param(sx_poll, int, 0);
-#endif
/*
* You can setup up to 4 boards.
@@ -2411,10 +2330,10 @@ static int __init specialix_init_module(void)
func_enter();
if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
- for(i = 0; i < SX_NBOARD; i++) {
+ for (i = 0; i < SX_NBOARD; i++) {
sx_board[i].base = iobase[i];
sx_board[i].irq = irq[i];
- sx_board[i].count= 0;
+ sx_board[i].count = 0;
}
}
@@ -2433,10 +2352,6 @@ static void __exit specialix_exit_module(void)
for (i = 0; i < SX_NBOARD; i++)
if (sx_board[i].flags & SX_BOARD_PRESENT)
sx_release_io_range(&sx_board[i]);
-#ifdef SPECIALIX_TIMER
- del_timer_sync(&missed_irq_timer);
-#endif
-
func_exit();
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 0243efb0be9..19db1eb87c2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1025,7 +1025,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
/*****************************************************************************/
-static void stl_putchar(struct tty_struct *tty, unsigned char ch)
+static int stl_putchar(struct tty_struct *tty, unsigned char ch)
{
struct stlport *portp;
unsigned int len;
@@ -1034,12 +1034,12 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
if (tty == NULL)
- return;
+ return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
if (portp->tx.buf == NULL)
- return;
+ return -EINVAL;
head = portp->tx.head;
tail = portp->tx.tail;
@@ -1053,6 +1053,7 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch)
head = portp->tx.buf;
}
portp->tx.head = head;
+ return 0;
}
/*****************************************************************************/
@@ -1255,7 +1256,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct stlport *portp;
- unsigned int ival;
int rc;
void __user *argp = (void __user *)arg;
@@ -1460,19 +1460,20 @@ static void stl_hangup(struct tty_struct *tty)
/*****************************************************************************/
-static void stl_breakctl(struct tty_struct *tty, int state)
+static int stl_breakctl(struct tty_struct *tty, int state)
{
struct stlport *portp;
pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
if (tty == NULL)
- return;
+ return -EINVAL;
portp = tty->driver_data;
if (portp == NULL)
- return;
+ return -EINVAL;
stl_sendbreak(portp, ((state == -1) ? 1 : 2));
+ return 0;
}
/*****************************************************************************/
@@ -4753,8 +4754,8 @@ static int __init stallion_module_init(void)
if (IS_ERR(stallion_class))
printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
- device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
- "staliomem%d", i);
+ device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+ NULL, "staliomem%d", i);
return 0;
err_unrtty:
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index d5cffcd6a57..2162439bbe4 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1840,7 +1840,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
return rc;
}
-static void sx_break(struct tty_struct *tty, int flag)
+static int sx_break(struct tty_struct *tty, int flag)
{
struct sx_port *port = tty->driver_data;
int rv;
@@ -1857,6 +1857,7 @@ static void sx_break(struct tty_struct *tty, int flag)
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
unlock_kernel();
func_exit();
+ return 0;
}
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 527d220aa4a..ef6706f0906 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
*
* Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear
- * Return Value: None
+ * Return Value: error code
*/
-static void mgsl_break(struct tty_struct *tty, int break_state)
+static int mgsl_break(struct tty_struct *tty, int break_state)
{
struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
unsigned long flags;
@@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->irq_spinlock,flags);
if (break_state == -1)
@@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
else
usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ return 0;
} /* end of mgsl_break() */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2c3e43bb2cc..3e9058993e4 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
/*
* generic HDLC support and callbacks
@@ -214,6 +214,7 @@ struct slgt_desc
char *buf; /* virtual address of data buffer */
unsigned int pdesc; /* physical address of this descriptor */
dma_addr_t buf_dma_addr;
+ unsigned short buf_count;
};
#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
@@ -302,7 +303,7 @@ struct slgt_info {
u32 idle_mode;
u32 max_frame_size; /* as set by device config */
- unsigned int raw_rx_size;
+ unsigned int rbuf_fill_level;
unsigned int if_mode;
/* device status */
@@ -466,6 +467,7 @@ static void tx_start(struct slgt_info *info);
static void tx_stop(struct slgt_info *info);
static void tx_set_idle(struct slgt_info *info);
static unsigned int free_tbuf_count(struct slgt_info *info);
+static unsigned int tbuf_bytes(struct slgt_info *info);
static void reset_tbufs(struct slgt_info *info);
static void tdma_reset(struct slgt_info *info);
static void tdma_start(struct slgt_info *info);
@@ -513,7 +515,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
@@ -849,6 +851,7 @@ static int write(struct tty_struct *tty,
int ret = 0;
struct slgt_info *info = tty->driver_data;
unsigned long flags;
+ unsigned int bufs_needed;
if (sanity_check(info, tty->name, "write"))
goto cleanup;
@@ -865,25 +868,16 @@ static int write(struct tty_struct *tty,
if (!count)
goto cleanup;
- if (info->params.mode == MGSL_MODE_RAW ||
- info->params.mode == MGSL_MODE_MONOSYNC ||
- info->params.mode == MGSL_MODE_BISYNC) {
- unsigned int bufs_needed = (count/DMABUFSIZE);
- unsigned int bufs_free = free_tbuf_count(info);
- if (count % DMABUFSIZE)
- ++bufs_needed;
- if (bufs_needed > bufs_free)
- goto cleanup;
- } else {
- if (info->tx_active)
- goto cleanup;
- if (info->tx_count) {
- /* send accumulated data from send_char() calls */
- /* as frame and wait before accepting more data. */
- tx_load(info, info->tx_buf, info->tx_count);
- goto start;
- }
+ if (!info->tx_active && info->tx_count) {
+ /* send accumulated data from send_char() */
+ tx_load(info, info->tx_buf, info->tx_count);
+ goto start;
}
+ bufs_needed = (count/DMABUFSIZE);
+ if (count % DMABUFSIZE)
+ ++bufs_needed;
+ if (bufs_needed > free_tbuf_count(info))
+ goto cleanup;
ret = info->tx_count = count;
tx_load(info, buf, count);
@@ -1396,10 +1390,12 @@ done:
static int chars_in_buffer(struct tty_struct *tty)
{
struct slgt_info *info = tty->driver_data;
+ int count;
if (sanity_check(info, tty->name, "chars_in_buffer"))
return 0;
- DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));
- return info->tx_count;
+ count = tbuf_bytes(info);
+ DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
+ return count;
}
/*
@@ -1452,14 +1448,14 @@ static void unthrottle(struct tty_struct * tty)
* set or clear transmit break condition
* break_state -1=set break condition, 0=clear
*/
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
{
struct slgt_info *info = tty->driver_data;
unsigned short value;
unsigned long flags;
if (sanity_check(info, tty->name, "set_break"))
- return;
+ return -EINVAL;
DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
spin_lock_irqsave(&info->lock,flags);
@@ -1470,6 +1466,7 @@ static void set_break(struct tty_struct *tty, int break_state)
value &= ~BIT6;
wr_reg16(info, TCR, value);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
#if SYNCLINK_GENERIC_HDLC
@@ -2679,8 +2676,31 @@ static int tx_abort(struct slgt_info *info)
static int rx_enable(struct slgt_info *info, int enable)
{
unsigned long flags;
- DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable));
+ unsigned int rbuf_fill_level;
+ DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
spin_lock_irqsave(&info->lock,flags);
+ /*
+ * enable[31..16] = receive DMA buffer fill level
+ * 0 = noop (leave fill level unchanged)
+ * fill level must be multiple of 4 and <= buffer size
+ */
+ rbuf_fill_level = ((unsigned int)enable) >> 16;
+ if (rbuf_fill_level) {
+ if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
+ spin_unlock_irqrestore(&info->lock, flags);
+ return -EINVAL;
+ }
+ info->rbuf_fill_level = rbuf_fill_level;
+ rx_stop(info); /* restart receiver to use new fill level */
+ }
+
+ /*
+ * enable[1..0] = receiver enable command
+ * 0 = disable
+ * 1 = enable
+ * 2 = enable or force hunt mode if already enabled
+ */
+ enable &= 3;
if (enable) {
if (!info->rx_enabled)
rx_start(info);
@@ -3447,7 +3467,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
- info->raw_rx_size = DMABUFSIZE;
+ info->rbuf_fill_level = DMABUFSIZE;
info->port.close_delay = 5*HZ/10;
info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
@@ -3934,15 +3954,7 @@ static void tdma_start(struct slgt_info *info)
/* set 1st descriptor address */
wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
- switch(info->params.mode) {
- case MGSL_MODE_RAW:
- case MGSL_MODE_MONOSYNC:
- case MGSL_MODE_BISYNC:
- wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
- break;
- default:
- wr_reg32(info, TDCSR, BIT0); /* DMA enable */
- }
+ wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
}
static void tx_stop(struct slgt_info *info)
@@ -4145,7 +4157,7 @@ static void sync_mode(struct slgt_info *info)
* 01 enable
* 00 auto-CTS enable
*/
- val = 0;
+ val = BIT2;
switch(info->params.mode) {
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
@@ -4418,6 +4430,8 @@ static void msc_set_vcr(struct slgt_info *info)
break;
}
+ if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
+ val |= BIT4;
if (info->signals & SerialSignal_DTR)
val |= BIT3;
if (info->signals & SerialSignal_RTS)
@@ -4456,16 +4470,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
while(!done) {
/* reset current buffer for reuse */
info->rbufs[i].status = 0;
- switch(info->params.mode) {
- case MGSL_MODE_RAW:
- case MGSL_MODE_MONOSYNC:
- case MGSL_MODE_BISYNC:
- set_desc_count(info->rbufs[i], info->raw_rx_size);
- break;
- default:
- set_desc_count(info->rbufs[i], DMABUFSIZE);
- }
-
+ set_desc_count(info->rbufs[i], info->rbuf_fill_level);
if (i == last)
done = 1;
if (++i == info->rbuf_count)
@@ -4572,7 +4577,7 @@ check_again:
DBGBH(("%s rx frame status=%04X size=%d\n",
info->device_name, status, framesize));
- DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
+ DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
if (framesize) {
if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
@@ -4592,7 +4597,7 @@ check_again:
info->icount.rxok++;
while(copy_count) {
- int partial_count = min(copy_count, DMABUFSIZE);
+ int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
memcpy(p, info->rbufs[i].buf, partial_count);
p += partial_count;
copy_count -= partial_count;
@@ -4684,6 +4689,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info)
}
/*
+ * return number of bytes in unsent transmit DMA buffers
+ * and the serial controller tx FIFO
+ */
+static unsigned int tbuf_bytes(struct slgt_info *info)
+{
+ unsigned int total_count = 0;
+ unsigned int i = info->tbuf_current;
+ unsigned int reg_value;
+ unsigned int count;
+ unsigned int active_buf_count = 0;
+
+ /*
+ * Add descriptor counts for all tx DMA buffers.
+ * If count is zero (cleared by DMA controller after read),
+ * the buffer is complete or is actively being read from.
+ *
+ * Record buf_count of last buffer with zero count starting
+ * from current ring position. buf_count is mirror
+ * copy of count and is not cleared by serial controller.
+ * If DMA controller is active, that buffer is actively
+ * being read so add to total.
+ */
+ do {
+ count = desc_count(info->tbufs[i]);
+ if (count)
+ total_count += count;
+ else if (!total_count)
+ active_buf_count = info->tbufs[i].buf_count;
+ if (++i == info->tbuf_count)
+ i = 0;
+ } while (i != info->tbuf_current);
+
+ /* read tx DMA status register */
+ reg_value = rd_reg32(info, TDCSR);
+
+ /* if tx DMA active, last zero count buffer is in use */
+ if (reg_value & BIT0)
+ total_count += active_buf_count;
+
+ /* add tx FIFO count = reg_value[15..8] */
+ total_count += (reg_value >> 8) & 0xff;
+
+ /* if transmitter active add one byte for shift register */
+ if (info->tx_active)
+ total_count++;
+
+ return total_count;
+}
+
+/*
* load transmit DMA buffer(s) with data
*/
static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
@@ -4721,6 +4776,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
set_desc_eof(*d, 0);
set_desc_count(*d, count);
+ d->buf_count = count;
}
info->tbuf_current = i;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 5768c413634..c0490cbd0db 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
#if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -552,7 +552,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
static void add_device(SLMP_INFO *info);
static void device_init(int adapter_num, struct pci_dev *pdev);
@@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty)
/* set or clear transmit break condition
* break_state -1=set break condition, 0=clear
*/
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
{
unsigned char RegValue;
SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
@@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state);
if (sanity_check(info, tty->name, "set_break"))
- return;
+ return -EINVAL;
spin_lock_irqsave(&info->lock,flags);
RegValue = read_reg(info, CTL);
@@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state)
RegValue &= ~BIT3;
write_reg(info, CTL, RegValue);
spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
}
#if SYNCLINK_GENERIC_HDLC
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 82f6a8c8633..6f4d856df98 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -656,558 +656,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
/**
- * tty_set_termios_ldisc - set ldisc field
- * @tty: tty structure
- * @num: line discipline number
- *
- * This is probably overkill for real world processors but
- * they are not on hot paths so a little discipline won't do
- * any harm.
- *
- * Locking: takes termios_mutex
- */
-
-static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
-{
- mutex_lock(&tty->termios_mutex);
- tty->termios->c_line = num;
- mutex_unlock(&tty->termios_mutex);
-}
-
-/*
- * This guards the refcounted line discipline lists. The lock
- * must be taken with irqs off because there are hangup path
- * callers who will do ldisc lookups and cannot sleep.
- */
-
-static DEFINE_SPINLOCK(tty_ldisc_lock);
-static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-/* Line disc dispatch table */
-static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
-
-/**
- * tty_register_ldisc - install a line discipline
- * @disc: ldisc number
- * @new_ldisc: pointer to the ldisc object
- *
- * Installs a new line discipline into the kernel. The discipline
- * is set up as unreferenced and then made available to the kernel
- * from this point onwards.
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
-{
- unsigned long flags;
- int ret = 0;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- tty_ldiscs[disc] = new_ldisc;
- new_ldisc->num = disc;
- new_ldisc->refcount = 0;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(tty_register_ldisc);
-
-/**
- * tty_unregister_ldisc - unload a line discipline
- * @disc: ldisc number
- * @new_ldisc: pointer to the ldisc object
- *
- * Remove a line discipline from the kernel providing it is not
- * currently in use.
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_unregister_ldisc(int disc)
-{
- unsigned long flags;
- int ret = 0;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (tty_ldiscs[disc]->refcount)
- ret = -EBUSY;
- else
- tty_ldiscs[disc] = NULL;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(tty_unregister_ldisc);
-
-
-/**
- * tty_ldisc_try_get - try and reference an ldisc
- * @disc: ldisc number
- * @ld: tty ldisc structure to complete
- *
- * Attempt to open and lock a line discipline into place. Return
- * the line discipline refcounted and assigned in ld. On an error
- * report the error code back
- */
-
-static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
-{
- unsigned long flags;
- struct tty_ldisc_ops *ldops;
- int err = -EINVAL;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld->ops = NULL;
- ldops = tty_ldiscs[disc];
- /* Check the entry is defined */
- if (ldops) {
- /* If the module is being unloaded we can't use it */
- if (!try_module_get(ldops->owner))
- err = -EAGAIN;
- else {
- /* lock it */
- ldops->refcount++;
- ld->ops = ldops;
- err = 0;
- }
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- return err;
-}
-
-/**
- * tty_ldisc_get - take a reference to an ldisc
- * @disc: ldisc number
- * @ld: tty line discipline structure to use
- *
- * Takes a reference to a line discipline. Deals with refcounts and
- * module locking counts. Returns NULL if the discipline is not available.
- * Returns a pointer to the discipline and bumps the ref count if it is
- * available
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
-{
- int err;
-
- if (disc < N_TTY || disc >= NR_LDISCS)
- return -EINVAL;
- err = tty_ldisc_try_get(disc, ld);
- if (err == -EAGAIN) {
- request_module("tty-ldisc-%d", disc);
- err = tty_ldisc_try_get(disc, ld);
- }
- return err;
-}
-
-/**
- * tty_ldisc_put - drop ldisc reference
- * @disc: ldisc number
- *
- * Drop a reference to a line discipline. Manage refcounts and
- * module usage counts
- *
- * Locking:
- * takes tty_ldisc_lock to guard against ldisc races
- */
-
-static void tty_ldisc_put(struct tty_ldisc_ops *ld)
-{
- unsigned long flags;
- int disc = ld->num;
-
- BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld = tty_ldiscs[disc];
- BUG_ON(ld->refcount == 0);
- ld->refcount--;
- module_put(ld->owner);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
-{
- return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
-{
- (*pos)++;
- return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
-{
-}
-
-static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
-{
- int i = *(loff_t *)v;
- struct tty_ldisc ld;
-
- if (tty_ldisc_get(i, &ld) < 0)
- return 0;
- seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
- tty_ldisc_put(ld.ops);
- return 0;
-}
-
-static const struct seq_operations tty_ldiscs_seq_ops = {
- .start = tty_ldiscs_seq_start,
- .next = tty_ldiscs_seq_next,
- .stop = tty_ldiscs_seq_stop,
- .show = tty_ldiscs_seq_show,
-};
-
-static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &tty_ldiscs_seq_ops);
-}
-
-const struct file_operations tty_ldiscs_proc_fops = {
- .owner = THIS_MODULE,
- .open = proc_tty_ldiscs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-/**
- * tty_ldisc_assign - set ldisc on a tty
- * @tty: tty to assign
- * @ld: line discipline
- *
- * Install an instance of a line discipline into a tty structure. The
- * ldisc must have a reference count above zero to ensure it remains/
- * The tty instance refcount starts at zero.
- *
- * Locking:
- * Caller must hold references
- */
-
-static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
-{
- ld->refcount = 0;
- tty->ldisc = *ld;
-}
-
-/**
- * tty_ldisc_try - internal helper
- * @tty: the tty
- *
- * Make a single attempt to grab and bump the refcount on
- * the tty ldisc. Return 0 on failure or 1 on success. This is
- * used to implement both the waiting and non waiting versions
- * of tty_ldisc_ref
- *
- * Locking: takes tty_ldisc_lock
- */
-
-static int tty_ldisc_try(struct tty_struct *tty)
-{
- unsigned long flags;
- struct tty_ldisc *ld;
- int ret = 0;
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- ld = &tty->ldisc;
- if (test_bit(TTY_LDISC, &tty->flags)) {
- ld->refcount++;
- ret = 1;
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- return ret;
-}
-
-/**
- * tty_ldisc_ref_wait - wait for the tty ldisc
- * @tty: tty device
- *
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * wait patiently until it changes.
- *
- * Note: Must not be called from an IRQ/timer context. The caller
- * must also be careful not to hold other locks that will deadlock
- * against a discipline change, such as an existing ldisc reference
- * (which we check for)
- *
- * Locking: call functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
-{
- /* wait_event is a macro */
- wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
- if (tty->ldisc.refcount == 0)
- printk(KERN_ERR "tty_ldisc_ref_wait\n");
- return &tty->ldisc;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
-
-/**
- * tty_ldisc_ref - get the tty ldisc
- * @tty: tty device
- *
- * Dereference the line discipline for the terminal and take a
- * reference to it. If the line discipline is in flux then
- * return NULL. Can be called from IRQ and timer functions.
- *
- * Locking: called functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
-{
- if (tty_ldisc_try(tty))
- return &tty->ldisc;
- return NULL;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref);
-
-/**
- * tty_ldisc_deref - free a tty ldisc reference
- * @ld: reference to free up
- *
- * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
- * be called in IRQ context.
- *
- * Locking: takes tty_ldisc_lock
- */
-
-void tty_ldisc_deref(struct tty_ldisc *ld)
-{
- unsigned long flags;
-
- BUG_ON(ld == NULL);
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (ld->refcount == 0)
- printk(KERN_ERR "tty_ldisc_deref: no references.\n");
- else
- ld->refcount--;
- if (ld->refcount == 0)
- wake_up(&tty_ldisc_wait);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
-
-/**
- * tty_ldisc_enable - allow ldisc use
- * @tty: terminal to activate ldisc on
- *
- * Set the TTY_LDISC flag when the line discipline can be called
- * again. Do necessary wakeups for existing sleepers.
- *
- * Note: nobody should set this bit except via this function. Clearing
- * directly is allowed.
- */
-
-static void tty_ldisc_enable(struct tty_struct *tty)
-{
- set_bit(TTY_LDISC, &tty->flags);
- wake_up(&tty_ldisc_wait);
-}
-
-/**
- * tty_ldisc_restore - helper for tty ldisc change
- * @tty: tty to recover
- * @old: previous ldisc
- *
- * Restore the previous line discipline or N_TTY when a line discipline
- * change fails due to an open error
- */
-
-static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
-{
- char buf[64];
- struct tty_ldisc new_ldisc;
-
- /* There is an outstanding reference here so this is safe */
- tty_ldisc_get(old->ops->num, old);
- tty_ldisc_assign(tty, old);
- tty_set_termios_ldisc(tty, old->ops->num);
- if (old->ops->open && (old->ops->open(tty) < 0)) {
- tty_ldisc_put(old->ops);
- /* This driver is always present */
- if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
- panic("n_tty: get");
- tty_ldisc_assign(tty, &new_ldisc);
- tty_set_termios_ldisc(tty, N_TTY);
- if (new_ldisc.ops->open) {
- int r = new_ldisc.ops->open(tty);
- if (r < 0)
- panic("Couldn't open N_TTY ldisc for "
- "%s --- error %d.",
- tty_name(tty, buf), r);
- }
- }
-}
-
-/**
- * tty_set_ldisc - set line discipline
- * @tty: the terminal to set
- * @ldisc: the line discipline
- *
- * Set the discipline of a tty line. Must be called from a process
- * context.
- *
- * Locking: takes tty_ldisc_lock.
- * called functions take termios_mutex
- */
-
-static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
-{
- int retval;
- struct tty_ldisc o_ldisc, new_ldisc;
- int work;
- unsigned long flags;
- struct tty_struct *o_tty;
-
-restart:
- /* This is a bit ugly for now but means we can break the 'ldisc
- is part of the tty struct' assumption later */
- retval = tty_ldisc_get(ldisc, &new_ldisc);
- if (retval)
- return retval;
-
- /*
- * Problem: What do we do if this blocks ?
- */
-
- tty_wait_until_sent(tty, 0);
-
- if (tty->ldisc.ops->num == ldisc) {
- tty_ldisc_put(new_ldisc.ops);
- return 0;
- }
-
- /*
- * No more input please, we are switching. The new ldisc
- * will update this value in the ldisc open function
- */
-
- tty->receive_room = 0;
-
- o_ldisc = tty->ldisc;
- o_tty = tty->link;
-
- /*
- * Make sure we don't change while someone holds a
- * reference to the line discipline. The TTY_LDISC bit
- * prevents anyone taking a reference once it is clear.
- * We need the lock to avoid racing reference takers.
- */
-
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
- if (tty->ldisc.refcount) {
- /* Free the new ldisc we grabbed. Must drop the lock
- first. */
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(o_ldisc.ops);
- /*
- * There are several reasons we may be busy, including
- * random momentary I/O traffic. We must therefore
- * retry. We could distinguish between blocking ops
- * and retries if we made tty_ldisc_wait() smarter.
- * That is up for discussion.
- */
- if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
- goto restart;
- }
- if (o_tty && o_tty->ldisc.refcount) {
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(o_tty->ldisc.ops);
- if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
- return -ERESTARTSYS;
- goto restart;
- }
- }
- /*
- * If the TTY_LDISC bit is set, then we are racing against
- * another ldisc change
- */
- if (!test_bit(TTY_LDISC, &tty->flags)) {
- struct tty_ldisc *ld;
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- tty_ldisc_put(new_ldisc.ops);
- ld = tty_ldisc_ref_wait(tty);
- tty_ldisc_deref(ld);
- goto restart;
- }
-
- clear_bit(TTY_LDISC, &tty->flags);
- if (o_tty)
- clear_bit(TTY_LDISC, &o_tty->flags);
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
- /*
- * From this point on we know nobody has an ldisc
- * usage reference, nor can they obtain one until
- * we say so later on.
- */
-
- work = cancel_delayed_work(&tty->buf.work);
- /*
- * Wait for ->hangup_work and ->buf.work handlers to terminate
- * MUST NOT hold locks here.
- */
- flush_scheduled_work();
- /* Shutdown the current discipline. */
- if (o_ldisc.ops->close)
- (o_ldisc.ops->close)(tty);
-
- /* Now set up the new line discipline. */
- tty_ldisc_assign(tty, &new_ldisc);
- tty_set_termios_ldisc(tty, ldisc);
- if (new_ldisc.ops->open)
- retval = (new_ldisc.ops->open)(tty);
- if (retval < 0) {
- tty_ldisc_put(new_ldisc.ops);
- tty_ldisc_restore(tty, &o_ldisc);
- }
- /* At this point we hold a reference to the new ldisc and a
- a reference to the old ldisc. If we ended up flipping back
- to the existing ldisc we have two references to it */
-
- if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
- tty->ops->set_ldisc(tty);
-
- tty_ldisc_put(o_ldisc.ops);
-
- /*
- * Allow ldisc referencing to occur as soon as the driver
- * ldisc callback completes.
- */
-
- tty_ldisc_enable(tty);
- if (o_tty)
- tty_ldisc_enable(o_tty);
-
- /* Restart it in case no characters kick it off. Safe if
- already running */
- if (work)
- schedule_delayed_work(&tty->buf.work, 1);
- return retval;
-}
-
-/**
* get_tty_driver - find device of a tty
* @dev_t: device identifier
* @index: returns the index of the tty
@@ -1467,7 +915,7 @@ static void tty_reset_termios(struct tty_struct *tty)
* do_tty_hangup - actual handler for hangup events
* @work: tty device
*
-k * This can be called by the "eventd" kernel thread. That is process
+ * This can be called by the "eventd" kernel thread. That is process
* synchronous but doesn't hold any locks, so we need to make sure we
* have the appropriate locks for what we're doing.
*
@@ -1671,19 +1119,6 @@ int tty_hung_up_p(struct file *filp)
EXPORT_SYMBOL(tty_hung_up_p);
-/**
- * is_tty - checker whether file is a TTY
- * @filp: file handle that may be a tty
- *
- * Check if the file handle is a tty handle.
- */
-
-int is_tty(struct file *filp)
-{
- return filp->f_op->read == tty_read
- || filp->f_op->read == hung_up_tty_read;
-}
-
static void session_clear_tty(struct pid *session)
{
struct task_struct *p;
@@ -2193,7 +1628,6 @@ static int init_dev(struct tty_driver *driver, int idx,
struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
int retval = 0;
- struct tty_ldisc *ld;
/* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -2342,25 +1776,12 @@ static int init_dev(struct tty_driver *driver, int idx,
* If we fail here just call release_tty to clean up. No need
* to decrement the use counts, as release_tty doesn't care.
*/
-
- ld = &tty->ldisc;
- if (ld->ops->open) {
- retval = (ld->ops->open)(tty);
- if (retval)
- goto release_mem_out;
- }
- if (o_tty && o_tty->ldisc.ops->open) {
- retval = (o_tty->ldisc.ops->open)(o_tty);
- if (retval) {
- if (ld->ops->close)
- (ld->ops->close)(tty);
- goto release_mem_out;
- }
- tty_ldisc_enable(o_tty);
- }
- tty_ldisc_enable(tty);
- goto success;
+ retval = tty_ldisc_setup(tty, o_tty);
+
+ if (retval)
+ goto release_mem_out;
+ goto success;
/*
* This fast open can be used if the tty is already open.
@@ -2498,12 +1919,10 @@ static void release_tty(struct tty_struct *tty, int idx)
static void release_dev(struct file *filp)
{
struct tty_struct *tty, *o_tty;
- struct tty_ldisc ld;
int pty_master, tty_closing, o_tty_closing, do_sleep;
int devpts;
int idx;
char buf[64];
- unsigned long flags;
tty = (struct tty_struct *)filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode,
@@ -2705,56 +2124,9 @@ static void release_dev(struct file *filp)
printk(KERN_DEBUG "freeing tty structure...");
#endif
/*
- * Prevent flush_to_ldisc() from rescheduling the work for later. Then
- * kill any delayed work. As this is the final close it does not
- * race with the set_ldisc code path.
+ * Ask the line discipline code to release its structures
*/
- clear_bit(TTY_LDISC, &tty->flags);
- cancel_delayed_work(&tty->buf.work);
-
- /*
- * Wait for ->hangup_work and ->buf.work handlers to terminate
- */
-
- flush_scheduled_work();
-
- /*
- * Wait for any short term users (we know they are just driver
- * side waiters as the file is closing so user count on the file
- * side is zero.
- */
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- while (tty->ldisc.refcount) {
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
- spin_lock_irqsave(&tty_ldisc_lock, flags);
- }
- spin_unlock_irqrestore(&tty_ldisc_lock, flags);
- /*
- * Shutdown the current line discipline, and reset it to N_TTY.
- *
- * FIXME: this MUST get fixed for the new reflocking
- */
- if (tty->ldisc.ops->close)
- (tty->ldisc.ops->close)(tty);
- tty_ldisc_put(tty->ldisc.ops);
-
- /*
- * Switch the line discipline back
- */
- WARN_ON(tty_ldisc_get(N_TTY, &ld));
- tty_ldisc_assign(tty, &ld);
- tty_set_termios_ldisc(tty, N_TTY);
- if (o_tty) {
- /* FIXME: could o_tty be in setldisc here ? */
- clear_bit(TTY_LDISC, &o_tty->flags);
- if (o_tty->ldisc.ops->close)
- (o_tty->ldisc.ops->close)(o_tty);
- tty_ldisc_put(o_tty->ldisc.ops);
- WARN_ON(tty_ldisc_get(N_TTY, &ld));
- tty_ldisc_assign(o_tty, &ld);
- tty_set_termios_ldisc(o_tty, N_TTY);
- }
+ tty_ldisc_release(tty, o_tty);
/*
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure.
@@ -3464,16 +2836,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
static int send_break(struct tty_struct *tty, unsigned int duration)
{
- if (tty_write_lock(tty, 0) < 0)
- return -EINTR;
- tty->ops->break_ctl(tty, -1);
- if (!signal_pending(current))
- msleep_interruptible(duration);
- tty->ops->break_ctl(tty, 0);
- tty_write_unlock(tty);
- if (signal_pending(current))
- return -EINTR;
- return 0;
+ int retval;
+
+ if (tty->ops->break_ctl == NULL)
+ return 0;
+
+ if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
+ retval = tty->ops->break_ctl(tty, duration);
+ else {
+ /* Do the work ourselves */
+ if (tty_write_lock(tty, 0) < 0)
+ return -EINTR;
+ retval = tty->ops->break_ctl(tty, -1);
+ if (retval)
+ goto out;
+ if (!signal_pending(current))
+ msleep_interruptible(duration);
+ retval = tty->ops->break_ctl(tty, 0);
+out:
+ tty_write_unlock(tty);
+ if (signal_pending(current))
+ retval = -EINTR;
+ }
+ return retval;
}
/**
@@ -3564,36 +2949,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link;
- /*
- * Break handling by driver
- */
-
- retval = -EINVAL;
-
- if (!tty->ops->break_ctl) {
- switch (cmd) {
- case TIOCSBRK:
- case TIOCCBRK:
- if (tty->ops->ioctl)
- retval = tty->ops->ioctl(tty, file, cmd, arg);
- if (retval != -EINVAL && retval != -ENOIOCTLCMD)
- printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
- return retval;
-
- /* These two ioctl's always return success; even if */
- /* the driver doesn't support them. */
- case TCSBRK:
- case TCSBRKP:
- if (!tty->ops->ioctl)
- return 0;
- retval = tty->ops->ioctl(tty, file, cmd, arg);
- if (retval != -EINVAL && retval != -ENOIOCTLCMD)
- printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
- if (retval == -ENOIOCTLCMD)
- retval = 0;
- return retval;
- }
- }
/*
* Factor out some common prep work
@@ -3615,6 +2970,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
+ /*
+ * Now do the stuff.
+ */
switch (cmd) {
case TIOCSTI:
return tiocsti(tty, p);
@@ -3658,12 +3016,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
*/
case TIOCSBRK: /* Turn break on, unconditionally */
if (tty->ops->break_ctl)
- tty->ops->break_ctl(tty, -1);
+ return tty->ops->break_ctl(tty, -1);
return 0;
-
case TIOCCBRK: /* Turn break off, unconditionally */
if (tty->ops->break_ctl)
- tty->ops->break_ctl(tty, 0);
+ return tty->ops->break_ctl(tty, 0);
return 0;
case TCSBRK: /* SVID version: non-zero arg --> no break */
/* non-zero arg means wait for all output data
@@ -3962,12 +3319,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
static void initialize_tty_struct(struct tty_struct *tty)
{
- struct tty_ldisc ld;
memset(tty, 0, sizeof(struct tty_struct));
tty->magic = TTY_MAGIC;
- if (tty_ldisc_get(N_TTY, &ld) < 0)
- panic("n_tty: init_tty");
- tty_ldisc_assign(tty, &ld);
+ tty_ldisc_init(tty);
tty->session = NULL;
tty->pgrp = NULL;
tty->overrun_time = jiffies;
@@ -4045,7 +3399,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
else
tty_line_name(driver, index, name);
- return device_create(tty_class, device, dev, name);
+ return device_create_drvdata(tty_class, device, dev, NULL, name);
}
/**
@@ -4280,7 +3634,7 @@ void __init console_init(void)
initcall_t *call;
/* Setup the default TTY line discipline. */
- (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+ tty_ldisc_begin();
/*
* set up the console device so that later boot sequences can
@@ -4323,20 +3677,22 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
+ "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+ "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
- device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -4344,7 +3700,7 @@ static int __init tty_init(void)
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
- device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
+ device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
new file mode 100644
index 00000000000..241cbdea65a
--- /dev/null
+++ b/drivers/char/tty_ldisc.c
@@ -0,0 +1,714 @@
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/kd.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+
+#include <linux/kmod.h>
+#include <linux/nsproxy.h>
+
+/*
+ * This guards the refcounted line discipline lists. The lock
+ * must be taken with irqs off because there are hangup path
+ * callers who will do ldisc lookups and cannot sleep.
+ */
+
+static DEFINE_SPINLOCK(tty_ldisc_lock);
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+/* Line disc dispatch table */
+static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
+
+/**
+ * tty_register_ldisc - install a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Installs a new line discipline into the kernel. The discipline
+ * is set up as unreferenced and then made available to the kernel
+ * from this point onwards.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ tty_ldiscs[disc] = new_ldisc;
+ new_ldisc->num = disc;
+ new_ldisc->refcount = 0;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_register_ldisc);
+
+/**
+ * tty_unregister_ldisc - unload a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Remove a line discipline from the kernel providing it is not
+ * currently in use.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_unregister_ldisc(int disc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty_ldiscs[disc]->refcount)
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc] = NULL;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
+
+/**
+ * tty_ldisc_try_get - try and reference an ldisc
+ * @disc: ldisc number
+ * @ld: tty ldisc structure to complete
+ *
+ * Attempt to open and lock a line discipline into place. Return
+ * the line discipline refcounted and assigned in ld. On an error
+ * report the error code back
+ */
+
+static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
+{
+ unsigned long flags;
+ struct tty_ldisc_ops *ldops;
+ int err = -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld->ops = NULL;
+ ldops = tty_ldiscs[disc];
+ /* Check the entry is defined */
+ if (ldops) {
+ /* If the module is being unloaded we can't use it */
+ if (!try_module_get(ldops->owner))
+ err = -EAGAIN;
+ else {
+ /* lock it */
+ ldops->refcount++;
+ ld->ops = ldops;
+ err = 0;
+ }
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ return err;
+}
+
+/**
+ * tty_ldisc_get - take a reference to an ldisc
+ * @disc: ldisc number
+ * @ld: tty line discipline structure to use
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and
+ * module locking counts. Returns NULL if the discipline is not available.
+ * Returns a pointer to the discipline and bumps the ref count if it is
+ * available
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
+{
+ int err;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+ err = tty_ldisc_try_get(disc, ld);
+ if (err == -EAGAIN) {
+ request_module("tty-ldisc-%d", disc);
+ err = tty_ldisc_try_get(disc, ld);
+ }
+ return err;
+}
+
+/**
+ * tty_ldisc_put - drop ldisc reference
+ * @disc: ldisc number
+ *
+ * Drop a reference to a line discipline. Manage refcounts and
+ * module usage counts
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static void tty_ldisc_put(struct tty_ldisc_ops *ld)
+{
+ unsigned long flags;
+ int disc = ld->num;
+
+ BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = tty_ldiscs[disc];
+ BUG_ON(ld->refcount == 0);
+ ld->refcount--;
+ module_put(ld->owner);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+{
+ return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
+{
+ int i = *(loff_t *)v;
+ struct tty_ldisc ld;
+
+ if (tty_ldisc_get(i, &ld) < 0)
+ return 0;
+ seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
+ tty_ldisc_put(ld.ops);
+ return 0;
+}
+
+static const struct seq_operations tty_ldiscs_seq_ops = {
+ .start = tty_ldiscs_seq_start,
+ .next = tty_ldiscs_seq_next,
+ .stop = tty_ldiscs_seq_stop,
+ .show = tty_ldiscs_seq_show,
+};
+
+static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &tty_ldiscs_seq_ops);
+}
+
+const struct file_operations tty_ldiscs_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = proc_tty_ldiscs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/**
+ * tty_ldisc_assign - set ldisc on a tty
+ * @tty: tty to assign
+ * @ld: line discipline
+ *
+ * Install an instance of a line discipline into a tty structure. The
+ * ldisc must have a reference count above zero to ensure it remains/
+ * The tty instance refcount starts at zero.
+ *
+ * Locking:
+ * Caller must hold references
+ */
+
+static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+ ld->refcount = 0;
+ tty->ldisc = *ld;
+}
+
+/**
+ * tty_ldisc_try - internal helper
+ * @tty: the tty
+ *
+ * Make a single attempt to grab and bump the refcount on
+ * the tty ldisc. Return 0 on failure or 1 on success. This is
+ * used to implement both the waiting and non waiting versions
+ * of tty_ldisc_ref
+ *
+ * Locking: takes tty_ldisc_lock
+ */
+
+static int tty_ldisc_try(struct tty_struct *tty)
+{
+ unsigned long flags;
+ struct tty_ldisc *ld;
+ int ret = 0;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ ld = &tty->ldisc;
+ if (test_bit(TTY_LDISC, &tty->flags)) {
+ ld->refcount++;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ return ret;
+}
+
+/**
+ * tty_ldisc_ref_wait - wait for the tty ldisc
+ * @tty: tty device
+ *
+ * Dereference the line discipline for the terminal and take a
+ * reference to it. If the line discipline is in flux then
+ * wait patiently until it changes.
+ *
+ * Note: Must not be called from an IRQ/timer context. The caller
+ * must also be careful not to hold other locks that will deadlock
+ * against a discipline change, such as an existing ldisc reference
+ * (which we check for)
+ *
+ * Locking: call functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+{
+ /* wait_event is a macro */
+ wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+ if (tty->ldisc.refcount == 0)
+ printk(KERN_ERR "tty_ldisc_ref_wait\n");
+ return &tty->ldisc;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
+
+/**
+ * tty_ldisc_ref - get the tty ldisc
+ * @tty: tty device
+ *
+ * Dereference the line discipline for the terminal and take a
+ * reference to it. If the line discipline is in flux then
+ * return NULL. Can be called from IRQ and timer functions.
+ *
+ * Locking: called functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+{
+ if (tty_ldisc_try(tty))
+ return &tty->ldisc;
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref);
+
+/**
+ * tty_ldisc_deref - free a tty ldisc reference
+ * @ld: reference to free up
+ *
+ * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
+ * be called in IRQ context.
+ *
+ * Locking: takes tty_ldisc_lock
+ */
+
+void tty_ldisc_deref(struct tty_ldisc *ld)
+{
+ unsigned long flags;
+
+ BUG_ON(ld == NULL);
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (ld->refcount == 0)
+ printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+ else
+ ld->refcount--;
+ if (ld->refcount == 0)
+ wake_up(&tty_ldisc_wait);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+
+/**
+ * tty_ldisc_enable - allow ldisc use
+ * @tty: terminal to activate ldisc on
+ *
+ * Set the TTY_LDISC flag when the line discipline can be called
+ * again. Do necessary wakeups for existing sleepers.
+ *
+ * Note: nobody should set this bit except via this function. Clearing
+ * directly is allowed.
+ */
+
+void tty_ldisc_enable(struct tty_struct *tty)
+{
+ set_bit(TTY_LDISC, &tty->flags);
+ wake_up(&tty_ldisc_wait);
+}
+
+/**
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @num: line discipline number
+ *
+ * This is probably overkill for real world processors but
+ * they are not on hot paths so a little discipline won't do
+ * any harm.
+ *
+ * Locking: takes termios_mutex
+ */
+
+static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
+{
+ mutex_lock(&tty->termios_mutex);
+ tty->termios->c_line = num;
+ mutex_unlock(&tty->termios_mutex);
+}
+
+
+/**
+ * tty_ldisc_restore - helper for tty ldisc change
+ * @tty: tty to recover
+ * @old: previous ldisc
+ *
+ * Restore the previous line discipline or N_TTY when a line discipline
+ * change fails due to an open error
+ */
+
+static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
+{
+ char buf[64];
+ struct tty_ldisc new_ldisc;
+
+ /* There is an outstanding reference here so this is safe */
+ tty_ldisc_get(old->ops->num, old);
+ tty_ldisc_assign(tty, old);
+ tty_set_termios_ldisc(tty, old->ops->num);
+ if (old->ops->open && (old->ops->open(tty) < 0)) {
+ tty_ldisc_put(old->ops);
+ /* This driver is always present */
+ if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
+ panic("n_tty: get");
+ tty_ldisc_assign(tty, &new_ldisc);
+ tty_set_termios_ldisc(tty, N_TTY);
+ if (new_ldisc.ops->open) {
+ int r = new_ldisc.ops->open(tty);
+ if (r < 0)
+ panic("Couldn't open N_TTY ldisc for "
+ "%s --- error %d.",
+ tty_name(tty, buf), r);
+ }
+ }
+}
+
+/**
+ * tty_set_ldisc - set line discipline
+ * @tty: the terminal to set
+ * @ldisc: the line discipline
+ *
+ * Set the discipline of a tty line. Must be called from a process
+ * context.
+ *
+ * Locking: takes tty_ldisc_lock.
+ * called functions take termios_mutex
+ */
+
+int tty_set_ldisc(struct tty_struct *tty, int ldisc)
+{
+ int retval;
+ struct tty_ldisc o_ldisc, new_ldisc;
+ int work;
+ unsigned long flags;
+ struct tty_struct *o_tty;
+
+restart:
+ /* This is a bit ugly for now but means we can break the 'ldisc
+ is part of the tty struct' assumption later */
+ retval = tty_ldisc_get(ldisc, &new_ldisc);
+ if (retval)
+ return retval;
+
+ /*
+ * Problem: What do we do if this blocks ?
+ */
+
+ tty_wait_until_sent(tty, 0);
+
+ if (tty->ldisc.ops->num == ldisc) {
+ tty_ldisc_put(new_ldisc.ops);
+ return 0;
+ }
+
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+
+ tty->receive_room = 0;
+
+ o_ldisc = tty->ldisc;
+ o_tty = tty->link;
+
+ /*
+ * Make sure we don't change while someone holds a
+ * reference to the line discipline. The TTY_LDISC bit
+ * prevents anyone taking a reference once it is clear.
+ * We need the lock to avoid racing reference takers.
+ */
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+ if (tty->ldisc.refcount) {
+ /* Free the new ldisc we grabbed. Must drop the lock
+ first. */
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(o_ldisc.ops);
+ /*
+ * There are several reasons we may be busy, including
+ * random momentary I/O traffic. We must therefore
+ * retry. We could distinguish between blocking ops
+ * and retries if we made tty_ldisc_wait() smarter.
+ * That is up for discussion.
+ */
+ if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ if (o_tty && o_tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(o_tty->ldisc.ops);
+ if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+ return -ERESTARTSYS;
+ goto restart;
+ }
+ }
+ /*
+ * If the TTY_LDISC bit is set, then we are racing against
+ * another ldisc change
+ */
+ if (!test_bit(TTY_LDISC, &tty->flags)) {
+ struct tty_ldisc *ld;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ tty_ldisc_put(new_ldisc.ops);
+ ld = tty_ldisc_ref_wait(tty);
+ tty_ldisc_deref(ld);
+ goto restart;
+ }
+
+ clear_bit(TTY_LDISC, &tty->flags);
+ if (o_tty)
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ /*
+ * From this point on we know nobody has an ldisc
+ * usage reference, nor can they obtain one until
+ * we say so later on.
+ */
+
+ work = cancel_delayed_work(&tty->buf.work);
+ /*
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
+ * MUST NOT hold locks here.
+ */
+ flush_scheduled_work();
+ /* Shutdown the current discipline. */
+ if (o_ldisc.ops->close)
+ (o_ldisc.ops->close)(tty);
+
+ /* Now set up the new line discipline. */
+ tty_ldisc_assign(tty, &new_ldisc);
+ tty_set_termios_ldisc(tty, ldisc);
+ if (new_ldisc.ops->open)
+ retval = (new_ldisc.ops->open)(tty);
+ if (retval < 0) {
+ tty_ldisc_put(new_ldisc.ops);
+ tty_ldisc_restore(tty, &o_ldisc);
+ }
+ /* At this point we hold a reference to the new ldisc and a
+ a reference to the old ldisc. If we ended up flipping back
+ to the existing ldisc we have two references to it */
+
+ if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
+ tty->ops->set_ldisc(tty);
+
+ tty_ldisc_put(o_ldisc.ops);
+
+ /*
+ * Allow ldisc referencing to occur as soon as the driver
+ * ldisc callback completes.
+ */
+
+ tty_ldisc_enable(tty);
+ if (o_tty)
+ tty_ldisc_enable(o_tty);
+
+ /* Restart it in case no characters kick it off. Safe if
+ already running */
+ if (work)
+ schedule_delayed_work(&tty->buf.work, 1);
+ return retval;
+}
+
+
+/**
+ * tty_ldisc_setup - open line discipline
+ * @tty: tty being shut down
+ * @o_tty: pair tty for pty/tty pairs
+ *
+ * Called during the initial open of a tty/pty pair in order to set up the
+ * line discplines and bind them to the tty.
+ */
+
+int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+ struct tty_ldisc *ld = &tty->ldisc;
+ int retval;
+
+ if (ld->ops->open) {
+ retval = (ld->ops->open)(tty);
+ if (retval)
+ return retval;
+ }
+ if (o_tty && o_tty->ldisc.ops->open) {
+ retval = (o_tty->ldisc.ops->open)(o_tty);
+ if (retval) {
+ if (ld->ops->close)
+ (ld->ops->close)(tty);
+ return retval;
+ }
+ tty_ldisc_enable(o_tty);
+ }
+ tty_ldisc_enable(tty);
+ return 0;
+}
+
+/**
+ * tty_ldisc_release - release line discipline
+ * @tty: tty being shut down
+ * @o_tty: pair tty for pty/tty pairs
+ *
+ * Called during the final close of a tty/pty pair in order to shut down the
+ * line discpline layer.
+ */
+
+void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+ unsigned long flags;
+ struct tty_ldisc ld;
+ /*
+ * Prevent flush_to_ldisc() from rescheduling the work for later. Then
+ * kill any delayed work. As this is the final close it does not
+ * race with the set_ldisc code path.
+ */
+ clear_bit(TTY_LDISC, &tty->flags);
+ cancel_delayed_work(&tty->buf.work);
+
+ /*
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
+ */
+
+ flush_scheduled_work();
+
+ /*
+ * Wait for any short term users (we know they are just driver
+ * side waiters as the file is closing so user count on the file
+ * side is zero.
+ */
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ while (tty->ldisc.refcount) {
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ }
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+ /*
+ * Shutdown the current line discipline, and reset it to N_TTY.
+ *
+ * FIXME: this MUST get fixed for the new reflocking
+ */
+ if (tty->ldisc.ops->close)
+ (tty->ldisc.ops->close)(tty);
+ tty_ldisc_put(tty->ldisc.ops);
+
+ /*
+ * Switch the line discipline back
+ */
+ WARN_ON(tty_ldisc_get(N_TTY, &ld));
+ tty_ldisc_assign(tty, &ld);
+ tty_set_termios_ldisc(tty, N_TTY);
+ if (o_tty) {
+ /* FIXME: could o_tty be in setldisc here ? */
+ clear_bit(TTY_LDISC, &o_tty->flags);
+ if (o_tty->ldisc.ops->close)
+ (o_tty->ldisc.ops->close)(o_tty);
+ tty_ldisc_put(o_tty->ldisc.ops);
+ WARN_ON(tty_ldisc_get(N_TTY, &ld));
+ tty_ldisc_assign(o_tty, &ld);
+ tty_set_termios_ldisc(o_tty, N_TTY);
+ }
+}
+
+/**
+ * tty_ldisc_init - ldisc setup for new tty
+ * @tty: tty being allocated
+ *
+ * Set up the line discipline objects for a newly allocated tty. Note that
+ * the tty structure is not completely set up when this call is made.
+ */
+
+void tty_ldisc_init(struct tty_struct *tty)
+{
+ struct tty_ldisc ld;
+ if (tty_ldisc_get(N_TTY, &ld) < 0)
+ panic("n_tty: init_tty");
+ tty_ldisc_assign(tty, &ld);
+}
+
+void tty_ldisc_begin(void)
+{
+ /* Setup the default TTY line discipline. */
+ (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+}
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index eebfad2777d..c2ae52dd53d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -481,10 +481,10 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty)
{
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
- "vcs%u", tty->index + 1);
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
- "vcsa%u", tty->index + 1);
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+ NULL, "vcs%u", tty->index + 1);
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+ NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@ int __init vcs_init(void)
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc");
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
- device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index e5da98d8f9c..7a70a40ad63 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
- device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
- "iseries!vt%d", i);
- device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
- "iseries!nvt%d", i);
+ device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
+ NULL, "iseries!vt%d", i);
+ device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ NULL, "iseries!nvt%d", i);
printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
"resource %10.10s type %4.4s, model %3.3s\n",
i, viotape_unitinfo[i].rsrcname,
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index f17ac043b55..69c5afe97f1 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data);
static irqreturn_t scc_stat_int(int irq, void *data);
static irqreturn_t scc_spcond_int(int irq, void *data);
static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static void scc_break_ctl(struct tty_struct *tty, int break_state);
+static int scc_break_ctl(struct tty_struct *tty, int break_state);
static struct tty_driver *scc_driver;
@@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
}
-static void scc_break_ctl(struct tty_struct *tty, int break_state)
+static int scc_break_ctl(struct tty_struct *tty, int break_state)
{
struct scc_port *port = (struct scc_port *)tty->driver_data;
unsigned long flags;
@@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
break_state ? TCR_SEND_BREAK : 0);
local_irq_restore(flags);
+ return 0;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 935f1c207a1..cb8c90da393 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -261,7 +261,7 @@ static void notify_update(struct vc_data *vc)
#ifdef VT_BUF_VRAM_ONLY
#define DO_UPDATE(vc) 0
#else
-#define DO_UPDATE(vc) CON_IS_VISIBLE(vc)
+#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked)
#endif
static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
@@ -2749,8 +2749,8 @@ static int con_open(struct tty_struct *tty, struct file *filp)
tty->termios->c_iflag |= IUTF8;
else
tty->termios->c_iflag &= ~IUTF8;
- release_console_sem();
vcs_make_sysfs(tty);
+ release_console_sem();
return ret;
}
}
@@ -2775,8 +2775,8 @@ static void con_close(struct tty_struct *tty, struct file *filp)
if (vc)
vc->vc_tty = NULL;
tty->driver_data = NULL;
- release_console_sem();
vcs_remove_sysfs(tty);
+ release_console_sem();
mutex_unlock(&tty_mutex);
/*
* tty_mutex is released, but we still hold BKL, so there is
@@ -3425,9 +3425,10 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
- con_driver->dev = device_create(vtconsole_class, NULL,
- MKDEV(0, con_driver->node),
- "vtcon%i", con_driver->node);
+ con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
+ MKDEV(0, con_driver->node),
+ NULL, "vtcon%i",
+ con_driver->node);
if (IS_ERR(con_driver->dev)) {
printk(KERN_WARNING "Unable to create device for %s; "
@@ -3535,9 +3536,10 @@ static int __init vtconsole_class_init(void)
struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->dev) {
- con->dev = device_create(vtconsole_class, NULL,
- MKDEV(0, con->node),
- "vtcon%i", con->node);
+ con->dev = device_create_drvdata(vtconsole_class, NULL,
+ MKDEV(0, con->node),
+ NULL, "vtcon%i",
+ con->node);
if (IS_ERR(con->dev)) {
printk(KERN_WARNING "Unable to create "
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 1e1b81e57cd..51966ccf4ea 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -658,8 +658,9 @@ static int __devinit hwicap_setup(struct device *dev, int id,
dev_err(dev, "cdev_add() failed\n");
goto failed3;
}
- /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
- device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id);
+
+ device_create_drvdata(icap_class, dev, devt, NULL,
+ "%s%d", DRIVER_NAME, id);
return 0; /* success */
failed3:
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1d41496ed2f..8d6a3ff0267 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -38,10 +38,10 @@
* also protects the cpufreq_cpu_data array.
*/
static struct cpufreq_driver *cpufreq_driver;
-static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */
-static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_governor *, cpufreq_cpu_governor);
#endif
static DEFINE_SPINLOCK(cpufreq_driver_lock);
@@ -135,7 +135,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
struct cpufreq_policy *data;
unsigned long flags;
- if (cpu >= NR_CPUS)
+ if (cpu >= nr_cpu_ids)
goto err_out;
/* get the cpufreq driver */
@@ -149,7 +149,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
/* get the CPU */
- data = cpufreq_cpu_data[cpu];
+ data = per_cpu(cpufreq_cpu_data, cpu);
if (!data)
goto err_out_put_module;
@@ -327,7 +327,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
dprintk("notification %u of frequency transition to %u kHz\n",
state, freqs->new);
- policy = cpufreq_cpu_data[freqs->cpu];
+ policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
switch (state) {
case CPUFREQ_PRECHANGE:
@@ -589,7 +589,7 @@ static ssize_t show_cpus(cpumask_t mask, char *buf)
ssize_t i = 0;
unsigned int cpu;
- for_each_cpu_mask(cpu, mask) {
+ for_each_cpu_mask_nr(cpu, mask) {
if (i)
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
@@ -828,14 +828,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
#ifdef CONFIG_SMP
#ifdef CONFIG_HOTPLUG_CPU
- if (cpufreq_cpu_governor[cpu]){
- policy->governor = cpufreq_cpu_governor[cpu];
+ if (per_cpu(cpufreq_cpu_governor, cpu)) {
+ policy->governor = per_cpu(cpufreq_cpu_governor, cpu);
dprintk("Restoring governor %s for cpu %d\n",
policy->governor->name, cpu);
}
#endif
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
if (cpu == j)
continue;
@@ -854,7 +854,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
spin_lock_irqsave(&cpufreq_driver_lock, flags);
managed_policy->cpus = policy->cpus;
- cpufreq_cpu_data[cpu] = managed_policy;
+ per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
dprintk("CPU already managed, adding link\n");
@@ -898,14 +898,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask(j, policy->cpus) {
- cpufreq_cpu_data[j] = policy;
+ for_each_cpu_mask_nr(j, policy->cpus) {
+ per_cpu(cpufreq_cpu_data, j) = policy;
per_cpu(policy_cpu, j) = policy->cpu;
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
/* symlink affected CPUs */
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
if (j == cpu)
continue;
if (!cpu_online(j))
@@ -945,8 +945,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask(j, policy->cpus)
- cpufreq_cpu_data[j] = NULL;
+ for_each_cpu_mask_nr(j, policy->cpus)
+ per_cpu(cpufreq_cpu_data, j) = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
kobject_put(&policy->kobj);
@@ -989,7 +989,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
dprintk("unregistering CPU %u\n", cpu);
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- data = cpufreq_cpu_data[cpu];
+ data = per_cpu(cpufreq_cpu_data, cpu);
if (!data) {
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -997,7 +997,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
unlock_policy_rwsem_write(cpu);
return -EINVAL;
}
- cpufreq_cpu_data[cpu] = NULL;
+ per_cpu(cpufreq_cpu_data, cpu) = NULL;
#ifdef CONFIG_SMP
@@ -1019,31 +1019,31 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
#ifdef CONFIG_SMP
#ifdef CONFIG_HOTPLUG_CPU
- cpufreq_cpu_governor[cpu] = data->governor;
+ per_cpu(cpufreq_cpu_governor, cpu) = data->governor;
#endif
/* if we have other CPUs still registered, we need to unlink them,
* or else wait_for_completion below will lock up. Clean the
- * cpufreq_cpu_data[] while holding the lock, and remove the sysfs
- * links afterwards.
+ * per_cpu(cpufreq_cpu_data) while holding the lock, and remove
+ * the sysfs links afterwards.
*/
if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask(j, data->cpus) {
+ for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
- cpufreq_cpu_data[j] = NULL;
+ per_cpu(cpufreq_cpu_data, j) = NULL;
}
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask(j, data->cpus) {
+ for_each_cpu_mask_nr(j, data->cpus) {
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);
#ifdef CONFIG_HOTPLUG_CPU
- cpufreq_cpu_governor[j] = data->governor;
+ per_cpu(cpufreq_cpu_governor, j) = data->governor;
#endif
cpu_sys_dev = get_cpu_sysdev(j);
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
@@ -1153,7 +1153,7 @@ EXPORT_SYMBOL(cpufreq_quick_get);
static unsigned int __cpufreq_get(unsigned int cpu)
{
- struct cpufreq_policy *policy = cpufreq_cpu_data[cpu];
+ struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
unsigned int ret_freq = 0;
if (!cpufreq_driver->get)
@@ -1822,16 +1822,19 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
cpufreq_driver = driver_data;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- ret = sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
+ ret = sysdev_driver_register(&cpu_sysdev_class,
+ &cpufreq_sysdev_driver);
if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) {
int i;
ret = -ENODEV;
/* check for at least one working CPU */
- for (i=0; i<NR_CPUS; i++)
- if (cpufreq_cpu_data[i])
+ for (i = 0; i < nr_cpu_ids; i++)
+ if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
ret = 0;
+ break;
+ }
/* if all ->init() calls failed, unregister */
if (ret) {
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 5d3a04ba6ad..fe565ee4375 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -497,7 +497,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index d2af20dda38..33855cb3cf1 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -367,7 +367,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
/* Get Idle Time */
idle_ticks = UINT_MAX;
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
cputime64_t total_idle_ticks;
unsigned int tmp_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
@@ -521,7 +521,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask(j, policy->cpus) {
+ for_each_cpu_mask_nr(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index ae70d63a8b2..c0ff97d375d 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -43,7 +43,7 @@ struct cpufreq_stats {
#endif
};
-static struct cpufreq_stats *cpufreq_stats_table[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table);
struct cpufreq_stats_attribute {
struct attribute attr;
@@ -58,7 +58,7 @@ cpufreq_stats_update (unsigned int cpu)
cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
- stat = cpufreq_stats_table[cpu];
+ stat = per_cpu(cpufreq_stats_table, cpu);
if (stat->time_in_state)
stat->time_in_state[stat->last_index] =
cputime64_add(stat->time_in_state[stat->last_index],
@@ -71,11 +71,11 @@ cpufreq_stats_update (unsigned int cpu)
static ssize_t
show_total_trans(struct cpufreq_policy *policy, char *buf)
{
- struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
if (!stat)
return 0;
return sprintf(buf, "%d\n",
- cpufreq_stats_table[stat->cpu]->total_trans);
+ per_cpu(cpufreq_stats_table, stat->cpu)->total_trans);
}
static ssize_t
@@ -83,7 +83,7 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
{
ssize_t len = 0;
int i;
- struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
if (!stat)
return 0;
cpufreq_stats_update(stat->cpu);
@@ -101,7 +101,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0;
int i, j;
- struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
if (!stat)
return 0;
cpufreq_stats_update(stat->cpu);
@@ -170,7 +170,7 @@ freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
static void cpufreq_stats_free_table(unsigned int cpu)
{
- struct cpufreq_stats *stat = cpufreq_stats_table[cpu];
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
if (policy && policy->cpu == cpu)
sysfs_remove_group(&policy->kobj, &stats_attr_group);
@@ -178,7 +178,7 @@ static void cpufreq_stats_free_table(unsigned int cpu)
kfree(stat->time_in_state);
kfree(stat);
}
- cpufreq_stats_table[cpu] = NULL;
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
if (policy)
cpufreq_cpu_put(policy);
}
@@ -192,7 +192,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
struct cpufreq_policy *data;
unsigned int alloc_size;
unsigned int cpu = policy->cpu;
- if (cpufreq_stats_table[cpu])
+ if (per_cpu(cpufreq_stats_table, cpu))
return -EBUSY;
if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -207,7 +207,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
goto error_out;
stat->cpu = cpu;
- cpufreq_stats_table[cpu] = stat;
+ per_cpu(cpufreq_stats_table, cpu) = stat;
for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
unsigned int freq = table[i].frequency;
@@ -251,7 +251,7 @@ error_out:
cpufreq_cpu_put(data);
error_get_fail:
kfree(stat);
- cpufreq_stats_table[cpu] = NULL;
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
return ret;
}
@@ -284,7 +284,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
if (val != CPUFREQ_POSTCHANGE)
return 0;
- stat = cpufreq_stats_table[freq->cpu];
+ stat = per_cpu(cpufreq_stats_table, freq->cpu);
if (!stat)
return 0;
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index cb2ac01a41a..32244aa7cc0 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -30,16 +30,18 @@
/**
* A few values needed by the userspace governor
*/
-static unsigned int cpu_max_freq[NR_CPUS];
-static unsigned int cpu_min_freq[NR_CPUS];
-static unsigned int cpu_cur_freq[NR_CPUS]; /* current CPU freq */
-static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
-static unsigned int cpu_is_managed[NR_CPUS];
+static DEFINE_PER_CPU(unsigned int, cpu_max_freq);
+static DEFINE_PER_CPU(unsigned int, cpu_min_freq);
+static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */
+static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by
+ userspace */
+static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
static DEFINE_MUTEX (userspace_mutex);
static int cpus_using_userspace_governor;
-#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
+#define dprintk(msg...) \
+ cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
/* keep track of frequency transitions */
static int
@@ -48,12 +50,12 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
- if (!cpu_is_managed[freq->cpu])
+ if (!per_cpu(cpu_is_managed, freq->cpu))
return 0;
dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
freq->cpu, freq->new);
- cpu_cur_freq[freq->cpu] = freq->new;
+ per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
return 0;
}
@@ -77,15 +79,15 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
mutex_lock(&userspace_mutex);
- if (!cpu_is_managed[policy->cpu])
+ if (!per_cpu(cpu_is_managed, policy->cpu))
goto err;
- cpu_set_freq[policy->cpu] = freq;
+ per_cpu(cpu_set_freq, policy->cpu) = freq;
- if (freq < cpu_min_freq[policy->cpu])
- freq = cpu_min_freq[policy->cpu];
- if (freq > cpu_max_freq[policy->cpu])
- freq = cpu_max_freq[policy->cpu];
+ if (freq < per_cpu(cpu_min_freq, policy->cpu))
+ freq = per_cpu(cpu_min_freq, policy->cpu);
+ if (freq > per_cpu(cpu_max_freq, policy->cpu))
+ freq = per_cpu(cpu_max_freq, policy->cpu);
/*
* We're safe from concurrent calls to ->target() here
@@ -104,7 +106,7 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
{
- return sprintf(buf, "%u\n", cpu_cur_freq[policy->cpu]);
+ return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu));
}
static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
@@ -127,12 +129,17 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
}
cpus_using_userspace_governor++;
- cpu_is_managed[cpu] = 1;
- cpu_min_freq[cpu] = policy->min;
- cpu_max_freq[cpu] = policy->max;
- cpu_cur_freq[cpu] = policy->cur;
- cpu_set_freq[cpu] = policy->cur;
- dprintk("managing cpu %u started (%u - %u kHz, currently %u kHz)\n", cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]);
+ per_cpu(cpu_is_managed, cpu) = 1;
+ per_cpu(cpu_min_freq, cpu) = policy->min;
+ per_cpu(cpu_max_freq, cpu) = policy->max;
+ per_cpu(cpu_cur_freq, cpu) = policy->cur;
+ per_cpu(cpu_set_freq, cpu) = policy->cur;
+ dprintk("managing cpu %u started "
+ "(%u - %u kHz, currently %u kHz)\n",
+ cpu,
+ per_cpu(cpu_min_freq, cpu),
+ per_cpu(cpu_max_freq, cpu),
+ per_cpu(cpu_cur_freq, cpu));
mutex_unlock(&userspace_mutex);
break;
@@ -145,34 +152,34 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
CPUFREQ_TRANSITION_NOTIFIER);
}
- cpu_is_managed[cpu] = 0;
- cpu_min_freq[cpu] = 0;
- cpu_max_freq[cpu] = 0;
- cpu_set_freq[cpu] = 0;
+ per_cpu(cpu_is_managed, cpu) = 0;
+ per_cpu(cpu_min_freq, cpu) = 0;
+ per_cpu(cpu_max_freq, cpu) = 0;
+ per_cpu(cpu_set_freq, cpu) = 0;
dprintk("managing cpu %u stopped\n", cpu);
mutex_unlock(&userspace_mutex);
break;
case CPUFREQ_GOV_LIMITS:
mutex_lock(&userspace_mutex);
- dprintk("limit event for cpu %u: %u - %u kHz,"
+ dprintk("limit event for cpu %u: %u - %u kHz, "
"currently %u kHz, last set to %u kHz\n",
cpu, policy->min, policy->max,
- cpu_cur_freq[cpu], cpu_set_freq[cpu]);
- if (policy->max < cpu_set_freq[cpu]) {
+ per_cpu(cpu_cur_freq, cpu),
+ per_cpu(cpu_set_freq, cpu));
+ if (policy->max < per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
- }
- else if (policy->min > cpu_set_freq[cpu]) {
+ } else if (policy->min > per_cpu(cpu_set_freq, cpu)) {
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
- }
- else {
- __cpufreq_driver_target(policy, cpu_set_freq[cpu],
+ } else {
+ __cpufreq_driver_target(policy,
+ per_cpu(cpu_set_freq, cpu),
CPUFREQ_RELATION_L);
}
- cpu_min_freq[cpu] = policy->min;
- cpu_max_freq[cpu] = policy->max;
- cpu_cur_freq[cpu] = policy->cur;
+ per_cpu(cpu_min_freq, cpu) = policy->min;
+ per_cpu(cpu_max_freq, cpu) = policy->max;
+ per_cpu(cpu_cur_freq, cpu) = policy->cur;
mutex_unlock(&userspace_mutex);
break;
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index b64c6bc445e..9071d80fbba 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -174,7 +174,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
-static struct cpufreq_frequency_table *show_table[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_frequency_table *, show_table);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
@@ -185,10 +185,10 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
ssize_t count = 0;
struct cpufreq_frequency_table *table;
- if (!show_table[cpu])
+ if (!per_cpu(show_table, cpu))
return -ENODEV;
- table = show_table[cpu];
+ table = per_cpu(show_table, cpu);
for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
@@ -217,20 +217,20 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu)
{
dprintk("setting show_table for cpu %u to %p\n", cpu, table);
- show_table[cpu] = table;
+ per_cpu(show_table, cpu) = table;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
dprintk("clearing show_table for cpu %u\n", cpu);
- show_table[cpu] = NULL;
+ per_cpu(show_table, cpu) = NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{
- return show_table[cpu];
+ return per_cpu(show_table, cpu);
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index e949618b9be..31a0e0b455b 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -21,7 +21,8 @@ static int __init cpuidle_sysfs_setup(char *unused)
}
__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
-static ssize_t show_available_governors(struct sys_device *dev, char *buf)
+static ssize_t show_available_governors(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t i = 0;
struct cpuidle_governor *tmp;
@@ -39,7 +40,8 @@ out:
return i;
}
-static ssize_t show_current_driver(struct sys_device *dev, char *buf)
+static ssize_t show_current_driver(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t ret;
@@ -53,7 +55,8 @@ static ssize_t show_current_driver(struct sys_device *dev, char *buf)
return ret;
}
-static ssize_t show_current_governor(struct sys_device *dev, char *buf)
+static ssize_t show_current_governor(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
{
ssize_t ret;
@@ -68,6 +71,7 @@ static ssize_t show_current_governor(struct sys_device *dev, char *buf)
}
static ssize_t store_current_governor(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf, size_t count)
{
char gov_name[CPUIDLE_NAME_LEN];
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index bf5b92f86df..ec249d2db63 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -28,13 +28,29 @@
#include <linux/device.h>
#include <linux/dca.h>
-MODULE_LICENSE("GPL");
+#define DCA_VERSION "1.4"
-/* For now we're assuming a single, global, DCA provider for the system. */
+MODULE_VERSION(DCA_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
static DEFINE_SPINLOCK(dca_lock);
-static struct dca_provider *global_dca = NULL;
+static LIST_HEAD(dca_providers);
+
+static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
+{
+ struct dca_provider *dca, *ret = NULL;
+
+ list_for_each_entry(dca, &dca_providers, node) {
+ if ((!dev) || (dca->ops->dev_managed(dca, dev))) {
+ ret = dca;
+ break;
+ }
+ }
+
+ return ret;
+}
/**
* dca_add_requester - add a dca client to the list
@@ -42,25 +58,39 @@ static struct dca_provider *global_dca = NULL;
*/
int dca_add_requester(struct device *dev)
{
- int err, slot;
+ struct dca_provider *dca;
+ int err, slot = -ENODEV;
- if (!global_dca)
- return -ENODEV;
+ if (!dev)
+ return -EFAULT;
spin_lock(&dca_lock);
- slot = global_dca->ops->add_requester(global_dca, dev);
- spin_unlock(&dca_lock);
- if (slot < 0)
+
+ /* check if the requester has not been added already */
+ dca = dca_find_provider_by_dev(dev);
+ if (dca) {
+ spin_unlock(&dca_lock);
+ return -EEXIST;
+ }
+
+ list_for_each_entry(dca, &dca_providers, node) {
+ slot = dca->ops->add_requester(dca, dev);
+ if (slot >= 0)
+ break;
+ }
+ if (slot < 0) {
+ spin_unlock(&dca_lock);
return slot;
+ }
- err = dca_sysfs_add_req(global_dca, dev, slot);
+ err = dca_sysfs_add_req(dca, dev, slot);
if (err) {
- spin_lock(&dca_lock);
- global_dca->ops->remove_requester(global_dca, dev);
+ dca->ops->remove_requester(dca, dev);
spin_unlock(&dca_lock);
return err;
}
+ spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_add_requester);
@@ -71,30 +101,78 @@ EXPORT_SYMBOL_GPL(dca_add_requester);
*/
int dca_remove_requester(struct device *dev)
{
+ struct dca_provider *dca;
int slot;
- if (!global_dca)
- return -ENODEV;
+
+ if (!dev)
+ return -EFAULT;
spin_lock(&dca_lock);
- slot = global_dca->ops->remove_requester(global_dca, dev);
- spin_unlock(&dca_lock);
- if (slot < 0)
+ dca = dca_find_provider_by_dev(dev);
+ if (!dca) {
+ spin_unlock(&dca_lock);
+ return -ENODEV;
+ }
+ slot = dca->ops->remove_requester(dca, dev);
+ if (slot < 0) {
+ spin_unlock(&dca_lock);
return slot;
+ }
- dca_sysfs_remove_req(global_dca, slot);
+ dca_sysfs_remove_req(dca, slot);
+
+ spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_remove_requester);
/**
- * dca_get_tag - return the dca tag for the given cpu
+ * dca_common_get_tag - return the dca tag (serves both new and old api)
+ * @dev - the device that wants dca service
* @cpu - the cpuid as returned by get_cpu()
*/
-u8 dca_get_tag(int cpu)
+u8 dca_common_get_tag(struct device *dev, int cpu)
{
- if (!global_dca)
+ struct dca_provider *dca;
+ u8 tag;
+
+ spin_lock(&dca_lock);
+
+ dca = dca_find_provider_by_dev(dev);
+ if (!dca) {
+ spin_unlock(&dca_lock);
return -ENODEV;
- return global_dca->ops->get_tag(global_dca, cpu);
+ }
+ tag = dca->ops->get_tag(dca, dev, cpu);
+
+ spin_unlock(&dca_lock);
+ return tag;
+}
+
+/**
+ * dca3_get_tag - return the dca tag to the requester device
+ * for the given cpu (new api)
+ * @dev - the device that wants dca service
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca3_get_tag(struct device *dev, int cpu)
+{
+ if (!dev)
+ return -EFAULT;
+
+ return dca_common_get_tag(dev, cpu);
+}
+EXPORT_SYMBOL_GPL(dca3_get_tag);
+
+/**
+ * dca_get_tag - return the dca tag for the given cpu (old api)
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca_get_tag(int cpu)
+{
+ struct device *dev = NULL;
+
+ return dca_common_get_tag(dev, cpu);
}
EXPORT_SYMBOL_GPL(dca_get_tag);
@@ -140,12 +218,10 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
- if (global_dca)
- return -EEXIST;
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
- global_dca = dca;
+ list_add(&dca->node, &dca_providers);
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
return 0;
@@ -158,11 +234,9 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
*/
void unregister_dca_provider(struct dca_provider *dca)
{
- if (!global_dca)
- return;
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);
- global_dca = NULL;
+ list_del(&dca->node);
dca_sysfs_remove_provider(dca);
}
EXPORT_SYMBOL_GPL(unregister_dca_provider);
@@ -187,6 +261,7 @@ EXPORT_SYMBOL_GPL(dca_unregister_notify);
static int __init dca_init(void)
{
+ printk(KERN_ERR "dca service started, version %s\n", DCA_VERSION);
return dca_sysfs_init();
}
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 011328faa5f..7af4b403bd2 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -13,9 +13,11 @@ static spinlock_t dca_idr_lock;
int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
{
struct device *cd;
+ static int req_count;
- cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1),
- "requester%d", slot);
+ cd = device_create_drvdata(dca_class, dca->cd,
+ MKDEV(0, slot + 1), NULL,
+ "requester%d", req_count++);
if (IS_ERR(cd))
return PTR_ERR(cd);
return 0;
@@ -46,7 +48,8 @@ idr_try_again:
return err;
}
- cd = device_create(dca_class, dev, MKDEV(0, 0), "dca%d", dca->id);
+ cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
+ "dca%d", dca->id);
if (IS_ERR(cd)) {
spin_lock(&dca_idr_lock);
idr_remove(&dca_idr, dca->id);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6239c3df30a..cd303901eb5 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -4,13 +4,14 @@
menuconfig DMADEVICES
bool "DMA Engine support"
- depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX || PPC
- depends on !HIGHMEM64G
+ depends on !HIGHMEM64G && HAS_DMA
help
DMA engines can do asynchronous data transfers without
involving the host CPU. Currently, this framework can be
used to offload memory copies in the network stack and
- RAID operations in the MD driver.
+ RAID operations in the MD driver. This menu only presents
+ DMA Device drivers supported by the configured arch, it may
+ be empty in some cases.
if DMADEVICES
@@ -37,6 +38,15 @@ config INTEL_IOP_ADMA
help
Enable support for the Intel(R) IOP Series RAID engines.
+config DW_DMAC
+ tristate "Synopsys DesignWare AHB DMA support"
+ depends on AVR32
+ select DMA_ENGINE
+ default y if CPU_AT32AP7000
+ help
+ Support the Synopsys DesignWare AHB DMA controller. This
+ can be integrated in chips such as the Atmel AT32ap7000.
+
config FSL_DMA
bool "Freescale MPC85xx/MPC83xx DMA support"
depends on PPC
@@ -46,6 +56,14 @@ config FSL_DMA
MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
The MPC8349, MPC8360 is also supported.
+config MV_XOR
+ bool "Marvell XOR engine support"
+ depends on PLAT_ORION
+ select ASYNC_CORE
+ select DMA_ENGINE
+ ---help---
+ Enable support for the Marvell XOR engine.
+
config DMA_ENGINE
bool
@@ -55,10 +73,19 @@ comment "DMA Clients"
config NET_DMA
bool "Network: TCP receive copy offload"
depends on DMA_ENGINE && NET
+ default (INTEL_IOATDMA || FSL_DMA)
help
This enables the use of DMA engines in the network stack to
offload receive copy-to-user operations, freeing CPU cycles.
- Since this is the main user of the DMA engine, it should be enabled;
- say Y here.
+
+ Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise
+ say N.
+
+config DMATEST
+ tristate "DMA Test client"
+ depends on DMA_ENGINE
+ help
+ Simple DMA test client. Say N unless you're debugging a
+ DMA Device driver.
endif
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index c8036d94590..14f59527d4f 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,6 +1,9 @@
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_MV_XOR) += mv_xor.o
+obj-$(CONFIG_DW_DMAC) += dw_dmac.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 97b329e7679..dc003a3a787 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -169,12 +169,18 @@ static void dma_client_chan_alloc(struct dma_client *client)
enum dma_state_client ack;
/* Find a channel */
- list_for_each_entry(device, &dma_device_list, global_node)
+ list_for_each_entry(device, &dma_device_list, global_node) {
+ /* Does the client require a specific DMA controller? */
+ if (client->slave && client->slave->dma_dev
+ && client->slave->dma_dev != device->dev)
+ continue;
+
list_for_each_entry(chan, &device->channels, device_node) {
if (!dma_chan_satisfies_mask(chan, client->cap_mask))
continue;
- desc = chan->device->device_alloc_chan_resources(chan);
+ desc = chan->device->device_alloc_chan_resources(
+ chan, client);
if (desc >= 0) {
ack = client->event_callback(client,
chan,
@@ -183,12 +189,14 @@ static void dma_client_chan_alloc(struct dma_client *client)
/* we are done once this client rejects
* an available resource
*/
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_get(chan);
- else if (ack == DMA_NAK)
+ chan->client_count++;
+ } else if (ack == DMA_NAK)
return;
}
}
+ }
}
enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
@@ -272,8 +280,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
/* client was holding resources for this channel so
* free it
*/
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_put(chan);
+ chan->client_count--;
+ }
}
mutex_unlock(&dma_list_mutex);
@@ -285,6 +295,10 @@ static void dma_clients_notify_removed(struct dma_chan *chan)
*/
void dma_async_client_register(struct dma_client *client)
{
+ /* validate client data */
+ BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) &&
+ !client->slave);
+
mutex_lock(&dma_list_mutex);
list_add_tail(&client->global_node, &dma_client_list);
mutex_unlock(&dma_list_mutex);
@@ -313,8 +327,10 @@ void dma_async_client_unregister(struct dma_client *client)
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);
- if (ack == DMA_ACK)
+ if (ack == DMA_ACK) {
dma_chan_put(chan);
+ chan->client_count--;
+ }
}
list_del(&client->global_node);
@@ -359,6 +375,10 @@ int dma_async_device_register(struct dma_device *device)
!device->device_prep_dma_memset);
BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
!device->device_prep_dma_interrupt);
+ BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+ !device->device_prep_slave_sg);
+ BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+ !device->device_terminate_all);
BUG_ON(!device->device_alloc_chan_resources);
BUG_ON(!device->device_free_chan_resources);
@@ -378,7 +398,7 @@ int dma_async_device_register(struct dma_device *device)
chan->chan_id = chancnt++;
chan->dev.class = &dma_devclass;
- chan->dev.parent = NULL;
+ chan->dev.parent = device->dev;
snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
device->dev_id, chan->chan_id);
@@ -394,6 +414,7 @@ int dma_async_device_register(struct dma_device *device)
kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
+ chan->client_count = 0;
chan->slow_ref = 0;
INIT_RCU_HEAD(&chan->rcu);
}
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
new file mode 100644
index 00000000000..a08d1970474
--- /dev/null
+++ b/drivers/dma/dmatest.c
@@ -0,0 +1,444 @@
+/*
+ * DMA Engine test module
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+
+static unsigned int test_buf_size = 16384;
+module_param(test_buf_size, uint, S_IRUGO);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static char test_channel[BUS_ID_SIZE];
+module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO);
+MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
+
+static char test_device[BUS_ID_SIZE];
+module_param_string(device, test_device, sizeof(test_device), S_IRUGO);
+MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
+
+static unsigned int threads_per_chan = 1;
+module_param(threads_per_chan, uint, S_IRUGO);
+MODULE_PARM_DESC(threads_per_chan,
+ "Number of threads to start per channel (default: 1)");
+
+static unsigned int max_channels;
+module_param(max_channels, uint, S_IRUGO);
+MODULE_PARM_DESC(nr_channels,
+ "Maximum number of channels to use (default: all)");
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC 0x80
+#define PATTERN_DST 0x00
+#define PATTERN_COPY 0x40
+#define PATTERN_OVERWRITE 0x20
+#define PATTERN_COUNT_MASK 0x1f
+
+struct dmatest_thread {
+ struct list_head node;
+ struct task_struct *task;
+ struct dma_chan *chan;
+ u8 *srcbuf;
+ u8 *dstbuf;
+};
+
+struct dmatest_chan {
+ struct list_head node;
+ struct dma_chan *chan;
+ struct list_head threads;
+};
+
+/*
+ * These are protected by dma_list_mutex since they're only used by
+ * the DMA client event callback
+ */
+static LIST_HEAD(dmatest_channels);
+static unsigned int nr_channels;
+
+static bool dmatest_match_channel(struct dma_chan *chan)
+{
+ if (test_channel[0] == '\0')
+ return true;
+ return strcmp(chan->dev.bus_id, test_channel) == 0;
+}
+
+static bool dmatest_match_device(struct dma_device *device)
+{
+ if (test_device[0] == '\0')
+ return true;
+ return strcmp(device->dev->bus_id, test_device) == 0;
+}
+
+static unsigned long dmatest_random(void)
+{
+ unsigned long buf;
+
+ get_random_bytes(&buf, sizeof(buf));
+ return buf;
+}
+
+static void dmatest_init_srcbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_SRC | PATTERN_COPY
+ | (~i & PATTERN_COUNT_MASK);;
+ for ( ; i < test_buf_size; i++)
+ buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_init_dstbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+ unsigned int i;
+
+ for (i = 0; i < start; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < start + len; i++)
+ buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+ | (~i & PATTERN_COUNT_MASK);
+ for ( ; i < test_buf_size; i++)
+ buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+ unsigned int counter, bool is_srcbuf)
+{
+ u8 diff = actual ^ pattern;
+ u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+ const char *thread_name = current->comm;
+
+ if (is_srcbuf)
+ pr_warning("%s: srcbuf[0x%x] overwritten!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if ((pattern & PATTERN_COPY)
+ && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+ pr_warning("%s: dstbuf[0x%x] not copied!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if (diff & PATTERN_SRC)
+ pr_warning("%s: dstbuf[0x%x] was copied!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else
+ pr_warning("%s: dstbuf[0x%x] mismatch!"
+ " Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 *buf, unsigned int start,
+ unsigned int end, unsigned int counter, u8 pattern,
+ bool is_srcbuf)
+{
+ unsigned int i;
+ unsigned int error_count = 0;
+ u8 actual;
+
+ for (i = start; i < end; i++) {
+ actual = buf[i];
+ if (actual != (pattern | (~counter & PATTERN_COUNT_MASK))) {
+ if (error_count < 32)
+ dmatest_mismatch(actual, pattern, i, counter,
+ is_srcbuf);
+ error_count++;
+ }
+ counter++;
+ }
+
+ if (error_count > 32)
+ pr_warning("%s: %u errors suppressed\n",
+ current->comm, error_count - 32);
+
+ return error_count;
+}
+
+/*
+ * This function repeatedly tests DMA transfers of various lengths and
+ * offsets until it is told to exit by kthread_stop(). There may be
+ * multiple threads running this function in parallel for a single
+ * channel, and there may be multiple channels being tested in
+ * parallel.
+ *
+ * Before each test, the source and destination buffer is initialized
+ * with a known pattern. This pattern is different depending on
+ * whether it's in an area which is supposed to be copied or
+ * overwritten, and different in the source and destination buffers.
+ * So if the DMA engine doesn't copy exactly what we tell it to copy,
+ * we'll notice.
+ */
+static int dmatest_func(void *data)
+{
+ struct dmatest_thread *thread = data;
+ struct dma_chan *chan;
+ const char *thread_name;
+ unsigned int src_off, dst_off, len;
+ unsigned int error_count;
+ unsigned int failed_tests = 0;
+ unsigned int total_tests = 0;
+ dma_cookie_t cookie;
+ enum dma_status status;
+ int ret;
+
+ thread_name = current->comm;
+
+ ret = -ENOMEM;
+ thread->srcbuf = kmalloc(test_buf_size, GFP_KERNEL);
+ if (!thread->srcbuf)
+ goto err_srcbuf;
+ thread->dstbuf = kmalloc(test_buf_size, GFP_KERNEL);
+ if (!thread->dstbuf)
+ goto err_dstbuf;
+
+ smp_rmb();
+ chan = thread->chan;
+ dma_chan_get(chan);
+
+ while (!kthread_should_stop()) {
+ total_tests++;
+
+ len = dmatest_random() % test_buf_size + 1;
+ src_off = dmatest_random() % (test_buf_size - len + 1);
+ dst_off = dmatest_random() % (test_buf_size - len + 1);
+
+ dmatest_init_srcbuf(thread->srcbuf, src_off, len);
+ dmatest_init_dstbuf(thread->dstbuf, dst_off, len);
+
+ cookie = dma_async_memcpy_buf_to_buf(chan,
+ thread->dstbuf + dst_off,
+ thread->srcbuf + src_off,
+ len);
+ if (dma_submit_error(cookie)) {
+ pr_warning("%s: #%u: submit error %d with src_off=0x%x "
+ "dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1, cookie,
+ src_off, dst_off, len);
+ msleep(100);
+ failed_tests++;
+ continue;
+ }
+ dma_async_memcpy_issue_pending(chan);
+
+ do {
+ msleep(1);
+ status = dma_async_memcpy_complete(
+ chan, cookie, NULL, NULL);
+ } while (status == DMA_IN_PROGRESS);
+
+ if (status == DMA_ERROR) {
+ pr_warning("%s: #%u: error during copy\n",
+ thread_name, total_tests - 1);
+ failed_tests++;
+ continue;
+ }
+
+ error_count = 0;
+
+ pr_debug("%s: verifying source buffer...\n", thread_name);
+ error_count += dmatest_verify(thread->srcbuf, 0, src_off,
+ 0, PATTERN_SRC, true);
+ error_count += dmatest_verify(thread->srcbuf, src_off,
+ src_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, true);
+ error_count += dmatest_verify(thread->srcbuf, src_off + len,
+ test_buf_size, src_off + len,
+ PATTERN_SRC, true);
+
+ pr_debug("%s: verifying dest buffer...\n",
+ thread->task->comm);
+ error_count += dmatest_verify(thread->dstbuf, 0, dst_off,
+ 0, PATTERN_DST, false);
+ error_count += dmatest_verify(thread->dstbuf, dst_off,
+ dst_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, false);
+ error_count += dmatest_verify(thread->dstbuf, dst_off + len,
+ test_buf_size, dst_off + len,
+ PATTERN_DST, false);
+
+ if (error_count) {
+ pr_warning("%s: #%u: %u errors with "
+ "src_off=0x%x dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1, error_count,
+ src_off, dst_off, len);
+ failed_tests++;
+ } else {
+ pr_debug("%s: #%u: No errors with "
+ "src_off=0x%x dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1,
+ src_off, dst_off, len);
+ }
+ }
+
+ ret = 0;
+ dma_chan_put(chan);
+ kfree(thread->dstbuf);
+err_dstbuf:
+ kfree(thread->srcbuf);
+err_srcbuf:
+ pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
+ thread_name, total_tests, failed_tests, ret);
+ return ret;
+}
+
+static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
+{
+ struct dmatest_thread *thread;
+ struct dmatest_thread *_thread;
+ int ret;
+
+ list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+ ret = kthread_stop(thread->task);
+ pr_debug("dmatest: thread %s exited with status %d\n",
+ thread->task->comm, ret);
+ list_del(&thread->node);
+ kfree(thread);
+ }
+ kfree(dtc);
+}
+
+static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
+{
+ struct dmatest_chan *dtc;
+ struct dmatest_thread *thread;
+ unsigned int i;
+
+ dtc = kmalloc(sizeof(struct dmatest_chan), GFP_ATOMIC);
+ if (!dtc) {
+ pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id);
+ return DMA_NAK;
+ }
+
+ dtc->chan = chan;
+ INIT_LIST_HEAD(&dtc->threads);
+
+ for (i = 0; i < threads_per_chan; i++) {
+ thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
+ if (!thread) {
+ pr_warning("dmatest: No memory for %s-test%u\n",
+ chan->dev.bus_id, i);
+ break;
+ }
+ thread->chan = dtc->chan;
+ smp_wmb();
+ thread->task = kthread_run(dmatest_func, thread, "%s-test%u",
+ chan->dev.bus_id, i);
+ if (IS_ERR(thread->task)) {
+ pr_warning("dmatest: Failed to run thread %s-test%u\n",
+ chan->dev.bus_id, i);
+ kfree(thread);
+ break;
+ }
+
+ /* srcbuf and dstbuf are allocated by the thread itself */
+
+ list_add_tail(&thread->node, &dtc->threads);
+ }
+
+ pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id);
+
+ list_add_tail(&dtc->node, &dmatest_channels);
+ nr_channels++;
+
+ return DMA_ACK;
+}
+
+static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan)
+{
+ struct dmatest_chan *dtc, *_dtc;
+
+ list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+ if (dtc->chan == chan) {
+ list_del(&dtc->node);
+ dmatest_cleanup_channel(dtc);
+ pr_debug("dmatest: lost channel %s\n",
+ chan->dev.bus_id);
+ return DMA_ACK;
+ }
+ }
+
+ return DMA_DUP;
+}
+
+/*
+ * Start testing threads as new channels are assigned to us, and kill
+ * them when the channels go away.
+ *
+ * When we unregister the client, all channels are removed so this
+ * will also take care of cleaning things up when the module is
+ * unloaded.
+ */
+static enum dma_state_client
+dmatest_event(struct dma_client *client, struct dma_chan *chan,
+ enum dma_state state)
+{
+ enum dma_state_client ack = DMA_NAK;
+
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ if (!dmatest_match_channel(chan)
+ || !dmatest_match_device(chan->device))
+ ack = DMA_DUP;
+ else if (max_channels && nr_channels >= max_channels)
+ ack = DMA_NAK;
+ else
+ ack = dmatest_add_channel(chan);
+ break;
+
+ case DMA_RESOURCE_REMOVED:
+ ack = dmatest_remove_channel(chan);
+ break;
+
+ default:
+ pr_info("dmatest: Unhandled event %u (%s)\n",
+ state, chan->dev.bus_id);
+ break;
+ }
+
+ return ack;
+}
+
+static struct dma_client dmatest_client = {
+ .event_callback = dmatest_event,
+};
+
+static int __init dmatest_init(void)
+{
+ dma_cap_set(DMA_MEMCPY, dmatest_client.cap_mask);
+ dma_async_client_register(&dmatest_client);
+ dma_async_client_chan_request(&dmatest_client);
+
+ return 0;
+}
+module_init(dmatest_init);
+
+static void __exit dmatest_exit(void)
+{
+ dma_async_client_unregister(&dmatest_client);
+}
+module_exit(dmatest_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
new file mode 100644
index 00000000000..94df9177124
--- /dev/null
+++ b/drivers/dma/dw_dmac.c
@@ -0,0 +1,1122 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007-2008 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "dw_dmac_regs.h"
+
+/*
+ * This supports the Synopsys "DesignWare AHB Central DMA Controller",
+ * (DW_ahb_dmac) which is used with various AMBA 2.0 systems (not all
+ * of which use ARM any more). See the "Databook" from Synopsys for
+ * information beyond what licensees probably provide.
+ *
+ * The driver has currently been tested only with the Atmel AT32AP7000,
+ * which does not support descriptor writeback.
+ */
+
+/* NOTE: DMS+SMS is system-specific. We should get this information
+ * from the platform code somehow.
+ */
+#define DWC_DEFAULT_CTLLO (DWC_CTLL_DST_MSIZE(0) \
+ | DWC_CTLL_SRC_MSIZE(0) \
+ | DWC_CTLL_DMS(0) \
+ | DWC_CTLL_SMS(1) \
+ | DWC_CTLL_LLP_D_EN \
+ | DWC_CTLL_LLP_S_EN)
+
+/*
+ * This is configuration-dependent and usually a funny size like 4095.
+ * Let's round it down to the nearest power of two.
+ *
+ * Note that this is a transfer count, i.e. if we transfer 32-bit
+ * words, we can do 8192 bytes per descriptor.
+ *
+ * This parameter is also system-specific.
+ */
+#define DWC_MAX_COUNT 2048U
+
+/*
+ * Number of descriptors to allocate for each channel. This should be
+ * made configurable somehow; preferably, the clients (at least the
+ * ones using slave transfers) should be able to give us a hint.
+ */
+#define NR_DESCS_PER_CHANNEL 64
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Because we're not relying on writeback from the controller (it may not
+ * even be configured into the core!) we don't need to use dma_pool. These
+ * descriptors -- and associated data -- are cacheable. We do need to make
+ * sure their dcache entries are written back before handing them off to
+ * the controller, though.
+ */
+
+static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
+{
+ return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
+{
+ return list_entry(dwc->queue.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
+{
+ struct dw_desc *desc, *_desc;
+ struct dw_desc *ret = NULL;
+ unsigned int i = 0;
+
+ spin_lock_bh(&dwc->lock);
+ list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) {
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del(&desc->desc_node);
+ ret = desc;
+ break;
+ }
+ dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc);
+ i++;
+ }
+ spin_unlock_bh(&dwc->lock);
+
+ dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i);
+
+ return ret;
+}
+
+static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ struct dw_desc *child;
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ child->txd.phys, sizeof(child->lli),
+ DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ desc->txd.phys, sizeof(desc->lli),
+ DMA_TO_DEVICE);
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ if (desc) {
+ struct dw_desc *child;
+
+ dwc_sync_desc_for_cpu(dwc, desc);
+
+ spin_lock_bh(&dwc->lock);
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ dev_vdbg(&dwc->chan.dev,
+ "moving child desc %p to freelist\n",
+ child);
+ list_splice_init(&desc->txd.tx_list, &dwc->free_list);
+ dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc);
+ list_add(&desc->desc_node, &dwc->free_list);
+ spin_unlock_bh(&dwc->lock);
+ }
+}
+
+/* Called with dwc->lock held and bh disabled */
+static dma_cookie_t
+dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ dma_cookie_t cookie = dwc->chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ dwc->chan.cookie = cookie;
+ desc->txd.cookie = cookie;
+
+ return cookie;
+}
+
+/*----------------------------------------------------------------------*/
+
+/* Called with dwc->lock held and bh disabled */
+static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
+{
+ struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_err(&dwc->chan.dev,
+ "BUG: Attempted to start non-idle channel\n");
+ dev_err(&dwc->chan.dev,
+ " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
+ channel_readl(dwc, SAR),
+ channel_readl(dwc, DAR),
+ channel_readl(dwc, LLP),
+ channel_readl(dwc, CTL_HI),
+ channel_readl(dwc, CTL_LO));
+
+ /* The tasklet will hopefully advance the queue... */
+ return;
+ }
+
+ channel_writel(dwc, LLP, first->txd.phys);
+ channel_writel(dwc, CTL_LO,
+ DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
+ channel_writel(dwc, CTL_HI, 0);
+ channel_set_bit(dw, CH_EN, dwc->mask);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+ dma_async_tx_callback callback;
+ void *param;
+ struct dma_async_tx_descriptor *txd = &desc->txd;
+
+ dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie);
+
+ dwc->completed = txd->cookie;
+ callback = txd->callback;
+ param = txd->callback_param;
+
+ dwc_sync_desc_for_cpu(dwc, desc);
+ list_splice_init(&txd->tx_list, &dwc->free_list);
+ list_move(&desc->desc_node, &dwc->free_list);
+
+ /*
+ * We use dma_unmap_page() regardless of how the buffers were
+ * mapped before they were submitted...
+ */
+ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))
+ dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len,
+ DMA_FROM_DEVICE);
+ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
+ dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len,
+ DMA_TO_DEVICE);
+
+ /*
+ * The API requires that no submissions are done from a
+ * callback, so we don't need to drop the lock here
+ */
+ if (callback)
+ callback(param);
+}
+
+static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_err(&dwc->chan.dev,
+ "BUG: XFER bit set, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+ }
+
+ /*
+ * Submit queued descriptors ASAP, i.e. before we go through
+ * the completed ones.
+ */
+ if (!list_empty(&dwc->queue))
+ dwc_dostart(dwc, dwc_first_queued(dwc));
+ list_splice_init(&dwc->active_list, &list);
+ list_splice_init(&dwc->queue, &dwc->active_list);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ dwc_descriptor_complete(dwc, desc);
+}
+
+static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ dma_addr_t llp;
+ struct dw_desc *desc, *_desc;
+ struct dw_desc *child;
+ u32 status_xfer;
+
+ /*
+ * Clear block interrupt flag before scanning so that we don't
+ * miss any, and read LLP before RAW_XFER to ensure it is
+ * valid if we decide to scan the list.
+ */
+ dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+ llp = channel_readl(dwc, LLP);
+ status_xfer = dma_readl(dw, RAW.XFER);
+
+ if (status_xfer & dwc->mask) {
+ /* Everything we've submitted is done */
+ dma_writel(dw, CLEAR.XFER, dwc->mask);
+ dwc_complete_all(dw, dwc);
+ return;
+ }
+
+ dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp);
+
+ list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
+ if (desc->lli.llp == llp)
+ /* This one is currently in progress */
+ return;
+
+ list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+ if (child->lli.llp == llp)
+ /* Currently in progress */
+ return;
+
+ /*
+ * No descriptors so far seem to be in progress, i.e.
+ * this one must be done.
+ */
+ dwc_descriptor_complete(dwc, desc);
+ }
+
+ dev_err(&dwc->chan.dev,
+ "BUG: All descriptors done, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+
+ if (!list_empty(&dwc->queue)) {
+ dwc_dostart(dwc, dwc_first_queued(dwc));
+ list_splice_init(&dwc->queue, &dwc->active_list);
+ }
+}
+
+static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
+{
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ " desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
+ lli->sar, lli->dar, lli->llp,
+ lli->ctlhi, lli->ctllo);
+}
+
+static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+ struct dw_desc *bad_desc;
+ struct dw_desc *child;
+
+ dwc_scan_descriptors(dw, dwc);
+
+ /*
+ * The descriptor currently at the head of the active list is
+ * borked. Since we don't have any way to report errors, we'll
+ * just have to scream loudly and try to carry on.
+ */
+ bad_desc = dwc_first_active(dwc);
+ list_del_init(&bad_desc->desc_node);
+ list_splice_init(&dwc->queue, dwc->active_list.prev);
+
+ /* Clear the error flag and try to restart the controller */
+ dma_writel(dw, CLEAR.ERROR, dwc->mask);
+ if (!list_empty(&dwc->active_list))
+ dwc_dostart(dwc, dwc_first_active(dwc));
+
+ /*
+ * KERN_CRITICAL may seem harsh, but since this only happens
+ * when someone submits a bad physical address in a
+ * descriptor, we should consider ourselves lucky that the
+ * controller flagged an error instead of scribbling over
+ * random memory locations.
+ */
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ "Bad descriptor submitted for DMA!\n");
+ dev_printk(KERN_CRIT, &dwc->chan.dev,
+ " cookie: %d\n", bad_desc->txd.cookie);
+ dwc_dump_lli(dwc, &bad_desc->lli);
+ list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+ dwc_dump_lli(dwc, &child->lli);
+
+ /* Pretend the descriptor completed successfully */
+ dwc_descriptor_complete(dwc, bad_desc);
+}
+
+static void dw_dma_tasklet(unsigned long data)
+{
+ struct dw_dma *dw = (struct dw_dma *)data;
+ struct dw_dma_chan *dwc;
+ u32 status_block;
+ u32 status_xfer;
+ u32 status_err;
+ int i;
+
+ status_block = dma_readl(dw, RAW.BLOCK);
+ status_xfer = dma_readl(dw, RAW.BLOCK);
+ status_err = dma_readl(dw, RAW.ERROR);
+
+ dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
+ status_block, status_err);
+
+ for (i = 0; i < dw->dma.chancnt; i++) {
+ dwc = &dw->chan[i];
+ spin_lock(&dwc->lock);
+ if (status_err & (1 << i))
+ dwc_handle_error(dw, dwc);
+ else if ((status_block | status_xfer) & (1 << i))
+ dwc_scan_descriptors(dw, dwc);
+ spin_unlock(&dwc->lock);
+ }
+
+ /*
+ * Re-enable interrupts. Block Complete interrupts are only
+ * enabled if the INT_EN bit in the descriptor is set. This
+ * will trigger a scan before the whole list is done.
+ */
+ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
+}
+
+static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
+{
+ struct dw_dma *dw = dev_id;
+ u32 status;
+
+ dev_vdbg(dw->dma.dev, "interrupt: status=0x%x\n",
+ dma_readl(dw, STATUS_INT));
+
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ status = dma_readl(dw, STATUS_INT);
+ if (status) {
+ dev_err(dw->dma.dev,
+ "BUG: Unexpected interrupts pending: 0x%x\n",
+ status);
+
+ /* Try to recover */
+ channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
+ }
+
+ tasklet_schedule(&dw->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct dw_desc *desc = txd_to_dw_desc(tx);
+ struct dw_dma_chan *dwc = to_dw_dma_chan(tx->chan);
+ dma_cookie_t cookie;
+
+ spin_lock_bh(&dwc->lock);
+ cookie = dwc_assign_cookie(dwc, desc);
+
+ /*
+ * REVISIT: We should attempt to chain as many descriptors as
+ * possible, perhaps even appending to those already submitted
+ * for DMA. But this is hard to do in a race-free manner.
+ */
+ if (list_empty(&dwc->active_list)) {
+ dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n",
+ desc->txd.cookie);
+ dwc_dostart(dwc, desc);
+ list_add_tail(&desc->desc_node, &dwc->active_list);
+ } else {
+ dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n",
+ desc->txd.cookie);
+
+ list_add_tail(&desc->desc_node, &dwc->queue);
+ }
+
+ spin_unlock_bh(&dwc->lock);
+
+ return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_desc *desc;
+ struct dw_desc *first;
+ struct dw_desc *prev;
+ size_t xfer_count;
+ size_t offset;
+ unsigned int src_width;
+ unsigned int dst_width;
+ u32 ctllo;
+
+ dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n",
+ dest, src, len, flags);
+
+ if (unlikely(!len)) {
+ dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n");
+ return NULL;
+ }
+
+ /*
+ * We can be a lot more clever here, but this should take care
+ * of the most common optimization.
+ */
+ if (!((src | dest | len) & 3))
+ src_width = dst_width = 2;
+ else if (!((src | dest | len) & 1))
+ src_width = dst_width = 1;
+ else
+ src_width = dst_width = 0;
+
+ ctllo = DWC_DEFAULT_CTLLO
+ | DWC_CTLL_DST_WIDTH(dst_width)
+ | DWC_CTLL_SRC_WIDTH(src_width)
+ | DWC_CTLL_DST_INC
+ | DWC_CTLL_SRC_INC
+ | DWC_CTLL_FC_M2M;
+ prev = first = NULL;
+
+ for (offset = 0; offset < len; offset += xfer_count << src_width) {
+ xfer_count = min_t(size_t, (len - offset) >> src_width,
+ DWC_MAX_COUNT);
+
+ desc = dwc_desc_get(dwc);
+ if (!desc)
+ goto err_desc_get;
+
+ desc->lli.sar = src + offset;
+ desc->lli.dar = dest + offset;
+ desc->lli.ctllo = ctllo;
+ desc->lli.ctlhi = xfer_count;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ }
+
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+
+ first->txd.flags = flags;
+ first->len = len;
+
+ return &first->txd;
+
+err_desc_get:
+ dwc_desc_put(dwc, first);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_data_direction direction,
+ unsigned long flags)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma_slave *dws = dwc->dws;
+ struct dw_desc *prev;
+ struct dw_desc *first;
+ u32 ctllo;
+ dma_addr_t reg;
+ unsigned int reg_width;
+ unsigned int mem_width;
+ unsigned int i;
+ struct scatterlist *sg;
+ size_t total_len = 0;
+
+ dev_vdbg(&chan->dev, "prep_dma_slave\n");
+
+ if (unlikely(!dws || !sg_len))
+ return NULL;
+
+ reg_width = dws->slave.reg_width;
+ prev = first = NULL;
+
+ sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction);
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ ctllo = (DWC_DEFAULT_CTLLO
+ | DWC_CTLL_DST_WIDTH(reg_width)
+ | DWC_CTLL_DST_FIX
+ | DWC_CTLL_SRC_INC
+ | DWC_CTLL_FC_M2P);
+ reg = dws->slave.tx_reg;
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct dw_desc *desc;
+ u32 len;
+ u32 mem;
+
+ desc = dwc_desc_get(dwc);
+ if (!desc) {
+ dev_err(&chan->dev,
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ mem = sg_phys(sg);
+ len = sg_dma_len(sg);
+ mem_width = 2;
+ if (unlikely(mem & 3 || len & 3))
+ mem_width = 0;
+
+ desc->lli.sar = mem;
+ desc->lli.dar = reg;
+ desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
+ desc->lli.ctlhi = len >> mem_width;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys,
+ sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ total_len += len;
+ }
+ break;
+ case DMA_FROM_DEVICE:
+ ctllo = (DWC_DEFAULT_CTLLO
+ | DWC_CTLL_SRC_WIDTH(reg_width)
+ | DWC_CTLL_DST_INC
+ | DWC_CTLL_SRC_FIX
+ | DWC_CTLL_FC_P2M);
+
+ reg = dws->slave.rx_reg;
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct dw_desc *desc;
+ u32 len;
+ u32 mem;
+
+ desc = dwc_desc_get(dwc);
+ if (!desc) {
+ dev_err(&chan->dev,
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ mem = sg_phys(sg);
+ len = sg_dma_len(sg);
+ mem_width = 2;
+ if (unlikely(mem & 3 || len & 3))
+ mem_width = 0;
+
+ desc->lli.sar = reg;
+ desc->lli.dar = mem;
+ desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
+ desc->lli.ctlhi = len >> reg_width;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys,
+ sizeof(prev->lli),
+ DMA_TO_DEVICE);
+ list_add_tail(&desc->desc_node,
+ &first->txd.tx_list);
+ }
+ prev = desc;
+ total_len += len;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ dma_sync_single_for_device(chan->dev.parent,
+ prev->txd.phys, sizeof(prev->lli),
+ DMA_TO_DEVICE);
+
+ first->len = total_len;
+
+ return &first->txd;
+
+err_desc_get:
+ dwc_desc_put(dwc, first);
+ return NULL;
+}
+
+static void dwc_terminate_all(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ /*
+ * This is only called when something went wrong elsewhere, so
+ * we don't really care about the data. Just disable the
+ * channel. We still have to poll the channel enable bit due
+ * to AHB/HSB limitations.
+ */
+ spin_lock_bh(&dwc->lock);
+
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+
+ while (dma_readl(dw, CH_EN) & dwc->mask)
+ cpu_relax();
+
+ /* active_list entries will end up before queued entries */
+ list_splice_init(&dwc->queue, &list);
+ list_splice_init(&dwc->active_list, &list);
+
+ spin_unlock_bh(&dwc->lock);
+
+ /* Flush all pending and queued descriptors */
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ dwc_descriptor_complete(dwc, desc);
+}
+
+static enum dma_status
+dwc_is_tx_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done, dma_cookie_t *used)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ int ret;
+
+ last_complete = dwc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret != DMA_SUCCESS) {
+ dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+
+ last_complete = dwc->completed;
+ last_used = chan->cookie;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ }
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return ret;
+}
+
+static void dwc_issue_pending(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+
+ spin_lock_bh(&dwc->lock);
+ if (!list_empty(&dwc->queue))
+ dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+ spin_unlock_bh(&dwc->lock);
+}
+
+static int dwc_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc;
+ struct dma_slave *slave;
+ struct dw_dma_slave *dws;
+ int i;
+ u32 cfghi;
+ u32 cfglo;
+
+ dev_vdbg(&chan->dev, "alloc_chan_resources\n");
+
+ /* Channels doing slave DMA can only handle one client. */
+ if (dwc->dws || client->slave) {
+ if (chan->client_count)
+ return -EBUSY;
+ }
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(dw, CH_EN) & dwc->mask) {
+ dev_dbg(&chan->dev, "DMA channel not idle?\n");
+ return -EIO;
+ }
+
+ dwc->completed = chan->cookie = 1;
+
+ cfghi = DWC_CFGH_FIFO_MODE;
+ cfglo = 0;
+
+ slave = client->slave;
+ if (slave) {
+ /*
+ * We need controller-specific data to set up slave
+ * transfers.
+ */
+ BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev);
+
+ dws = container_of(slave, struct dw_dma_slave, slave);
+
+ dwc->dws = dws;
+ cfghi = dws->cfg_hi;
+ cfglo = dws->cfg_lo;
+ } else {
+ dwc->dws = NULL;
+ }
+
+ channel_writel(dwc, CFG_LO, cfglo);
+ channel_writel(dwc, CFG_HI, cfghi);
+
+ /*
+ * NOTE: some controllers may have additional features that we
+ * need to initialize here, like "scatter-gather" (which
+ * doesn't mean what you think it means), and status writeback.
+ */
+
+ spin_lock_bh(&dwc->lock);
+ i = dwc->descs_allocated;
+ while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
+ spin_unlock_bh(&dwc->lock);
+
+ desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL);
+ if (!desc) {
+ dev_info(&chan->dev,
+ "only allocated %d descriptors\n", i);
+ spin_lock_bh(&dwc->lock);
+ break;
+ }
+
+ dma_async_tx_descriptor_init(&desc->txd, chan);
+ desc->txd.tx_submit = dwc_tx_submit;
+ desc->txd.flags = DMA_CTRL_ACK;
+ INIT_LIST_HEAD(&desc->txd.tx_list);
+ desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli,
+ sizeof(desc->lli), DMA_TO_DEVICE);
+ dwc_desc_put(dwc, desc);
+
+ spin_lock_bh(&dwc->lock);
+ i = ++dwc->descs_allocated;
+ }
+
+ /* Enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dwc->mask);
+ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+ spin_unlock_bh(&dwc->lock);
+
+ dev_dbg(&chan->dev,
+ "alloc_chan_resources allocated %d descriptors\n", i);
+
+ return i;
+}
+
+static void dwc_free_chan_resources(struct dma_chan *chan)
+{
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_desc *desc, *_desc;
+ LIST_HEAD(list);
+
+ dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n",
+ dwc->descs_allocated);
+
+ /* ASSERT: channel is idle */
+ BUG_ON(!list_empty(&dwc->active_list));
+ BUG_ON(!list_empty(&dwc->queue));
+ BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask);
+
+ spin_lock_bh(&dwc->lock);
+ list_splice_init(&dwc->free_list, &list);
+ dwc->descs_allocated = 0;
+ dwc->dws = NULL;
+
+ /* Disable interrupts */
+ channel_clear_bit(dw, MASK.XFER, dwc->mask);
+ channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_clear_bit(dw, MASK.ERROR, dwc->mask);
+
+ spin_unlock_bh(&dwc->lock);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+ dev_vdbg(&chan->dev, " freeing descriptor %p\n", desc);
+ dma_unmap_single(chan->dev.parent, desc->txd.phys,
+ sizeof(desc->lli), DMA_TO_DEVICE);
+ kfree(desc);
+ }
+
+ dev_vdbg(&chan->dev, "free_chan_resources done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static void dw_dma_off(struct dw_dma *dw)
+{
+ dma_writel(dw, CFG, 0);
+
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
+ cpu_relax();
+}
+
+static int __init dw_probe(struct platform_device *pdev)
+{
+ struct dw_dma_platform_data *pdata;
+ struct resource *io;
+ struct dw_dma *dw;
+ size_t size;
+ int irq;
+ int err;
+ int i;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
+ return -EINVAL;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io)
+ return -EINVAL;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ size = sizeof(struct dw_dma);
+ size += pdata->nr_channels * sizeof(struct dw_dma_chan);
+ dw = kzalloc(size, GFP_KERNEL);
+ if (!dw)
+ return -ENOMEM;
+
+ if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) {
+ err = -EBUSY;
+ goto err_kfree;
+ }
+
+ memset(dw, 0, sizeof *dw);
+
+ dw->regs = ioremap(io->start, DW_REGLEN);
+ if (!dw->regs) {
+ err = -ENOMEM;
+ goto err_release_r;
+ }
+
+ dw->clk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(dw->clk)) {
+ err = PTR_ERR(dw->clk);
+ goto err_clk;
+ }
+ clk_enable(dw->clk);
+
+ /* force dma off, just in case */
+ dw_dma_off(dw);
+
+ err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw);
+ if (err)
+ goto err_irq;
+
+ platform_set_drvdata(pdev, dw);
+
+ tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
+
+ dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
+
+ INIT_LIST_HEAD(&dw->dma.channels);
+ for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+ struct dw_dma_chan *dwc = &dw->chan[i];
+
+ dwc->chan.device = &dw->dma;
+ dwc->chan.cookie = dwc->completed = 1;
+ dwc->chan.chan_id = i;
+ list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
+
+ dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
+ spin_lock_init(&dwc->lock);
+ dwc->mask = 1 << i;
+
+ INIT_LIST_HEAD(&dwc->active_list);
+ INIT_LIST_HEAD(&dwc->queue);
+ INIT_LIST_HEAD(&dwc->free_list);
+
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ }
+
+ /* Clear/disable all interrupts on all channels. */
+ dma_writel(dw, CLEAR.XFER, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
+ dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
+
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+ dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+ dw->dma.dev = &pdev->dev;
+ dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
+ dw->dma.device_free_chan_resources = dwc_free_chan_resources;
+
+ dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy;
+
+ dw->dma.device_prep_slave_sg = dwc_prep_slave_sg;
+ dw->dma.device_terminate_all = dwc_terminate_all;
+
+ dw->dma.device_is_tx_complete = dwc_is_tx_complete;
+ dw->dma.device_issue_pending = dwc_issue_pending;
+
+ dma_writel(dw, CFG, DW_CFG_DMA_EN);
+
+ printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
+ pdev->dev.bus_id, dw->dma.chancnt);
+
+ dma_async_device_register(&dw->dma);
+
+ return 0;
+
+err_irq:
+ clk_disable(dw->clk);
+ clk_put(dw->clk);
+err_clk:
+ iounmap(dw->regs);
+ dw->regs = NULL;
+err_release_r:
+ release_resource(io);
+err_kfree:
+ kfree(dw);
+ return err;
+}
+
+static int __exit dw_remove(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+ struct dw_dma_chan *dwc, *_dwc;
+ struct resource *io;
+
+ dw_dma_off(dw);
+ dma_async_device_unregister(&dw->dma);
+
+ free_irq(platform_get_irq(pdev, 0), dw);
+ tasklet_kill(&dw->tasklet);
+
+ list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
+ chan.device_node) {
+ list_del(&dwc->chan.device_node);
+ channel_clear_bit(dw, CH_EN, dwc->mask);
+ }
+
+ clk_disable(dw->clk);
+ clk_put(dw->clk);
+
+ iounmap(dw->regs);
+ dw->regs = NULL;
+
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(io->start, DW_REGLEN);
+
+ kfree(dw);
+
+ return 0;
+}
+
+static void dw_shutdown(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ dw_dma_off(platform_get_drvdata(pdev));
+ clk_disable(dw->clk);
+}
+
+static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ dw_dma_off(platform_get_drvdata(pdev));
+ clk_disable(dw->clk);
+ return 0;
+}
+
+static int dw_resume_early(struct platform_device *pdev)
+{
+ struct dw_dma *dw = platform_get_drvdata(pdev);
+
+ clk_enable(dw->clk);
+ dma_writel(dw, CFG, DW_CFG_DMA_EN);
+ return 0;
+
+}
+
+static struct platform_driver dw_driver = {
+ .remove = __exit_p(dw_remove),
+ .shutdown = dw_shutdown,
+ .suspend_late = dw_suspend_late,
+ .resume_early = dw_resume_early,
+ .driver = {
+ .name = "dw_dmac",
+ },
+};
+
+static int __init dw_init(void)
+{
+ return platform_driver_probe(&dw_driver, dw_probe);
+}
+module_init(dw_init);
+
+static void __exit dw_exit(void)
+{
+ platform_driver_unregister(&dw_driver);
+}
+module_exit(dw_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>");
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
new file mode 100644
index 00000000000..00fdd187bb0
--- /dev/null
+++ b/drivers/dma/dw_dmac_regs.h
@@ -0,0 +1,225 @@
+/*
+ * Driver for the Synopsys DesignWare AHB DMA Controller
+ *
+ * Copyright (C) 2005-2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/dw_dmac.h>
+
+#define DW_DMA_MAX_NR_CHANNELS 8
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#define DW_REG(name) u32 name; u32 __pad_##name
+
+/* Hardware register definitions. */
+struct dw_dma_chan_regs {
+ DW_REG(SAR); /* Source Address Register */
+ DW_REG(DAR); /* Destination Address Register */
+ DW_REG(LLP); /* Linked List Pointer */
+ u32 CTL_LO; /* Control Register Low */
+ u32 CTL_HI; /* Control Register High */
+ DW_REG(SSTAT);
+ DW_REG(DSTAT);
+ DW_REG(SSTATAR);
+ DW_REG(DSTATAR);
+ u32 CFG_LO; /* Configuration Register Low */
+ u32 CFG_HI; /* Configuration Register High */
+ DW_REG(SGR);
+ DW_REG(DSR);
+};
+
+struct dw_dma_irq_regs {
+ DW_REG(XFER);
+ DW_REG(BLOCK);
+ DW_REG(SRC_TRAN);
+ DW_REG(DST_TRAN);
+ DW_REG(ERROR);
+};
+
+struct dw_dma_regs {
+ /* per-channel registers */
+ struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS];
+
+ /* irq handling */
+ struct dw_dma_irq_regs RAW; /* r */
+ struct dw_dma_irq_regs STATUS; /* r (raw & mask) */
+ struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */
+ struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */
+
+ DW_REG(STATUS_INT); /* r */
+
+ /* software handshaking */
+ DW_REG(REQ_SRC);
+ DW_REG(REQ_DST);
+ DW_REG(SGL_REQ_SRC);
+ DW_REG(SGL_REQ_DST);
+ DW_REG(LAST_SRC);
+ DW_REG(LAST_DST);
+
+ /* miscellaneous */
+ DW_REG(CFG);
+ DW_REG(CH_EN);
+ DW_REG(ID);
+ DW_REG(TEST);
+
+ /* optional encoded params, 0x3c8..0x3 */
+};
+
+/* Bitfields in CTL_LO */
+#define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */
+#define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */
+#define DWC_CTLL_SRC_WIDTH(n) ((n)<<4)
+#define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */
+#define DWC_CTLL_DST_DEC (1<<7)
+#define DWC_CTLL_DST_FIX (2<<7)
+#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */
+#define DWC_CTLL_SRC_DEC (1<<9)
+#define DWC_CTLL_SRC_FIX (2<<9)
+#define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */
+#define DWC_CTLL_SRC_MSIZE(n) ((n)<<14)
+#define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */
+#define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */
+#define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */
+#define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */
+#define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */
+#define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */
+/* plus 4 transfer types for peripheral-as-flow-controller */
+#define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */
+#define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */
+#define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */
+#define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */
+
+/* Bitfields in CTL_HI */
+#define DWC_CTLH_DONE 0x00001000
+#define DWC_CTLH_BLOCK_TS_MASK 0x00000fff
+
+/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */
+#define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */
+#define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */
+#define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */
+#define DWC_CFGL_MAX_BURST(x) ((x) << 20)
+#define DWC_CFGL_RELOAD_SAR (1 << 30)
+#define DWC_CFGL_RELOAD_DAR (1 << 31)
+
+/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGH_DS_UPD_EN (1 << 5)
+#define DWC_CFGH_SS_UPD_EN (1 << 6)
+
+/* Bitfields in SGR */
+#define DWC_SGR_SGI(x) ((x) << 0)
+#define DWC_SGR_SGC(x) ((x) << 20)
+
+/* Bitfields in DSR */
+#define DWC_DSR_DSI(x) ((x) << 0)
+#define DWC_DSR_DSC(x) ((x) << 20)
+
+/* Bitfields in CFG */
+#define DW_CFG_DMA_EN (1 << 0)
+
+#define DW_REGLEN 0x400
+
+struct dw_dma_chan {
+ struct dma_chan chan;
+ void __iomem *ch_regs;
+ u8 mask;
+
+ spinlock_t lock;
+
+ /* these other elements are all protected by lock */
+ dma_cookie_t completed;
+ struct list_head active_list;
+ struct list_head queue;
+ struct list_head free_list;
+
+ struct dw_dma_slave *dws;
+
+ unsigned int descs_allocated;
+};
+
+static inline struct dw_dma_chan_regs __iomem *
+__dwc_regs(struct dw_dma_chan *dwc)
+{
+ return dwc->ch_regs;
+}
+
+#define channel_readl(dwc, name) \
+ __raw_readl(&(__dwc_regs(dwc)->name))
+#define channel_writel(dwc, name, val) \
+ __raw_writel((val), &(__dwc_regs(dwc)->name))
+
+static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct dw_dma_chan, chan);
+}
+
+
+struct dw_dma {
+ struct dma_device dma;
+ void __iomem *regs;
+ struct tasklet_struct tasklet;
+ struct clk *clk;
+
+ u8 all_chan_mask;
+
+ struct dw_dma_chan chan[0];
+};
+
+static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
+{
+ return dw->regs;
+}
+
+#define dma_readl(dw, name) \
+ __raw_readl(&(__dw_regs(dw)->name))
+#define dma_writel(dw, name, val) \
+ __raw_writel((val), &(__dw_regs(dw)->name))
+
+#define channel_set_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | (mask))
+#define channel_clear_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | 0)
+
+static inline struct dw_dma *to_dw_dma(struct dma_device *ddev)
+{
+ return container_of(ddev, struct dw_dma, dma);
+}
+
+/* LLI == Linked List Item; a.k.a. DMA block descriptor */
+struct dw_lli {
+ /* values that are not changed by hardware */
+ dma_addr_t sar;
+ dma_addr_t dar;
+ dma_addr_t llp; /* chain to next lli */
+ u32 ctllo;
+ /* values that may get written back: */
+ u32 ctlhi;
+ /* sstat and dstat can snapshot peripheral register state.
+ * silicon config may discard either or both...
+ */
+ u32 sstat;
+ u32 dstat;
+};
+
+struct dw_desc {
+ /* FIRST values the hardware uses */
+ struct dw_lli lli;
+
+ /* THEN values for driver housekeeping */
+ struct list_head desc_node;
+ struct dma_async_tx_descriptor txd;
+ size_t len;
+};
+
+static inline struct dw_desc *
+txd_to_dw_desc(struct dma_async_tx_descriptor *txd)
+{
+ return container_of(txd, struct dw_desc, txd);
+}
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 054eabffc18..c0059ca5834 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -366,7 +366,8 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
*
* Return - The number of descriptors allocated.
*/
-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+static int fsl_dma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
LIST_HEAD(tmp_list);
@@ -809,8 +810,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
if (!src) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc memory for test!\n");
- err = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
dest = src + test_size;
@@ -820,7 +820,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
chan = &fsl_chan->common;
- if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc resources for DMA\n");
err = -ENODEV;
@@ -842,13 +842,13 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
if (fsl_dma_is_complete(chan, cookie, NULL, NULL) != DMA_SUCCESS) {
dev_err(fsl_chan->dev, "selftest: Time out!\n");
err = -ENODEV;
- goto out;
+ goto free_resources;
}
/* Test free and re-alloc channel resources */
fsl_dma_free_chan_resources(chan);
- if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
dev_err(fsl_chan->dev,
"selftest: Cannot alloc resources for DMA\n");
err = -ENODEV;
@@ -927,8 +927,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (!new_fsl_chan) {
dev_err(&dev->dev, "No free memory for allocating "
"dma channels!\n");
- err = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
/* get dma channel register base */
@@ -936,7 +935,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
dev->node->full_name);
- goto err;
+ goto err_no_reg;
}
new_fsl_chan->feature = *(u32 *)match->data;
@@ -958,7 +957,7 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
dev_err(&dev->dev, "There is no %d channel!\n",
new_fsl_chan->id);
err = -EINVAL;
- goto err;
+ goto err_no_chan;
}
fdev->chan[new_fsl_chan->id] = new_fsl_chan;
tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
@@ -997,23 +996,26 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "DMA channel %s request_irq error "
"with return %d\n", dev->node->full_name, err);
- goto err;
+ goto err_no_irq;
}
}
err = fsl_dma_self_test(new_fsl_chan);
if (err)
- goto err;
+ goto err_self_test;
dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
match->compatible, new_fsl_chan->irq);
return 0;
-err:
- dma_halt(new_fsl_chan);
- iounmap(new_fsl_chan->reg_base);
+
+err_self_test:
free_irq(new_fsl_chan->irq, new_fsl_chan);
+err_no_irq:
list_del(&new_fsl_chan->common.device_node);
+err_no_chan:
+ iounmap(new_fsl_chan->reg_base);
+err_no_reg:
kfree(new_fsl_chan);
return err;
}
@@ -1054,8 +1056,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
if (!fdev) {
dev_err(&dev->dev, "No enough memory for 'priv'\n");
- err = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
fdev->dev = &dev->dev;
INIT_LIST_HEAD(&fdev->common.channels);
@@ -1065,7 +1066,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
if (err) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
dev->node->full_name);
- goto err;
+ goto err_no_reg;
}
dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
@@ -1103,6 +1104,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
err:
iounmap(fdev->reg_base);
+err_no_reg:
kfree(fdev);
return err;
}
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index 16e0fd8facf..9b16a3af9a0 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -47,6 +47,16 @@ static struct pci_device_id ioat_pci_tbl[] = {
/* I/OAT v2 platforms */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
+
+ /* I/OAT v3 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },
{ 0, }
};
@@ -83,6 +93,11 @@ static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
if (device->dma && ioat_dca_enabled)
device->dca = ioat2_dca_init(pdev, iobase);
break;
+ case IOAT_VER_3_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat3_dca_init(pdev, iobase);
+ break;
default:
err = -ENODEV;
break;
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index 9e922760b7f..6cf622da028 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -37,12 +37,18 @@
#include "ioatdma_registers.h"
/*
- * Bit 16 of a tag map entry is the "valid" bit, if it is set then bits 0:15
+ * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6
* contain the bit number of the APIC ID to map into the DCA tag. If the valid
* bit is not set, then the value must be 0 or 1 and defines the bit in the tag.
*/
#define DCA_TAG_MAP_VALID 0x80
+#define DCA3_TAG_MAP_BIT_TO_INV 0x80
+#define DCA3_TAG_MAP_BIT_TO_SEL 0x40
+#define DCA3_TAG_MAP_LITERAL_VAL 0x1
+
+#define DCA_TAG_MAP_MASK 0xDF
+
/*
* "Legacy" DCA systems do not implement the DCA register set in the
* I/OAT device. Software needs direct support for their tag mappings.
@@ -95,6 +101,7 @@ struct ioat_dca_slot {
};
#define IOAT_DCA_MAX_REQ 6
+#define IOAT3_DCA_MAX_REQ 2
struct ioat_dca_priv {
void __iomem *iobase;
@@ -171,7 +178,9 @@ static int ioat_dca_remove_requester(struct dca_provider *dca,
return -ENODEV;
}
-static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
{
struct ioat_dca_priv *ioatdca = dca_priv(dca);
int i, apic_id, bit, value;
@@ -193,10 +202,26 @@ static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
return tag;
}
+static int ioat_dca_dev_managed(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+
+ pdev = to_pci_dev(dev);
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev)
+ return 1;
+ }
+ return 0;
+}
+
static struct dca_ops ioat_dca_ops = {
.add_requester = ioat_dca_add_requester,
.remove_requester = ioat_dca_remove_requester,
.get_tag = ioat_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
};
@@ -207,6 +232,8 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
u8 *tag_map = NULL;
int i;
int err;
+ u8 version;
+ u8 max_requesters;
if (!system_has_dca_enabled(pdev))
return NULL;
@@ -237,15 +264,20 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
if (tag_map == NULL)
return NULL;
+ version = readb(iobase + IOAT_VER_OFFSET);
+ if (version == IOAT_VER_3_0)
+ max_requesters = IOAT3_DCA_MAX_REQ;
+ else
+ max_requesters = IOAT_DCA_MAX_REQ;
+
dca = alloc_dca_provider(&ioat_dca_ops,
sizeof(*ioatdca) +
- (sizeof(struct ioat_dca_slot) * IOAT_DCA_MAX_REQ));
+ (sizeof(struct ioat_dca_slot) * max_requesters));
if (!dca)
return NULL;
ioatdca = dca_priv(dca);
- ioatdca->max_requesters = IOAT_DCA_MAX_REQ;
-
+ ioatdca->max_requesters = max_requesters;
ioatdca->dca_base = iobase + 0x54;
/* copy over the APIC ID to DCA tag mapping */
@@ -323,11 +355,13 @@ static int ioat2_dca_remove_requester(struct dca_provider *dca,
return -ENODEV;
}
-static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat2_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
{
u8 tag;
- tag = ioat_dca_get_tag(dca, cpu);
+ tag = ioat_dca_get_tag(dca, dev, cpu);
tag = (~tag) & 0x1F;
return tag;
}
@@ -336,6 +370,7 @@ static struct dca_ops ioat2_dca_ops = {
.add_requester = ioat2_dca_add_requester,
.remove_requester = ioat2_dca_remove_requester,
.get_tag = ioat2_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
};
static int ioat2_dca_count_dca_slots(void __iomem *iobase, u16 dca_offset)
@@ -425,3 +460,198 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
return dca;
}
+
+static int ioat3_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+ writel(id | IOAT_DCA_GREQID_VALID,
+ ioatdca->iobase + global_req_table + (i * 4));
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat3_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+ writel(0, ioatdca->iobase + global_req_table + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat3_dca_get_tag(struct dca_provider *dca,
+ struct device *dev,
+ int cpu)
+{
+ u8 tag;
+
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ int i, apic_id, bit, value;
+ u8 entry;
+
+ tag = 0;
+ apic_id = cpu_physical_id(cpu);
+
+ for (i = 0; i < IOAT_TAG_MAP_LEN; i++) {
+ entry = ioatdca->tag_map[i];
+ if (entry & DCA3_TAG_MAP_BIT_TO_SEL) {
+ bit = entry &
+ ~(DCA3_TAG_MAP_BIT_TO_SEL | DCA3_TAG_MAP_BIT_TO_INV);
+ value = (apic_id & (1 << bit)) ? 1 : 0;
+ } else if (entry & DCA3_TAG_MAP_BIT_TO_INV) {
+ bit = entry & ~DCA3_TAG_MAP_BIT_TO_INV;
+ value = (apic_id & (1 << bit)) ? 0 : 1;
+ } else {
+ value = (entry & DCA3_TAG_MAP_LITERAL_VAL) ? 1 : 0;
+ }
+ tag |= (value << i);
+ }
+
+ return tag;
+}
+
+static struct dca_ops ioat3_dca_ops = {
+ .add_requester = ioat3_dca_add_requester,
+ .remove_requester = ioat3_dca_remove_requester,
+ .get_tag = ioat3_dca_get_tag,
+ .dev_managed = ioat_dca_dev_managed,
+};
+
+static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+ int slots = 0;
+ u32 req;
+ u16 global_req_table;
+
+ global_req_table = readw(iobase + dca_offset + IOAT3_DCA_GREQID_OFFSET);
+ if (global_req_table == 0)
+ return 0;
+
+ do {
+ req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+ slots++;
+ } while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+ return slots;
+}
+
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ int slots;
+ int i;
+ int err;
+ u16 dca_offset;
+ u16 csi_fsb_control;
+ u16 pcie_control;
+ u8 bit;
+
+ union {
+ u64 full;
+ struct {
+ u32 low;
+ u32 high;
+ };
+ } tag_map;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+ if (dca_offset == 0)
+ return NULL;
+
+ slots = ioat3_dca_count_dca_slots(iobase, dca_offset);
+ if (slots == 0)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat3_dca_ops,
+ sizeof(*ioatdca)
+ + (sizeof(struct ioat_dca_slot) * slots));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->iobase = iobase;
+ ioatdca->dca_base = iobase + dca_offset;
+ ioatdca->max_requesters = slots;
+
+ /* some bios might not know to turn these on */
+ csi_fsb_control = readw(ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+ if ((csi_fsb_control & IOAT3_CSI_CONTROL_PREFETCH) == 0) {
+ csi_fsb_control |= IOAT3_CSI_CONTROL_PREFETCH;
+ writew(csi_fsb_control,
+ ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+ }
+ pcie_control = readw(ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+ if ((pcie_control & IOAT3_PCI_CONTROL_MEMWR) == 0) {
+ pcie_control |= IOAT3_PCI_CONTROL_MEMWR;
+ writew(pcie_control,
+ ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+ }
+
+
+ /* TODO version, compatibility and configuration checks */
+
+ /* copy out the APIC to DCA tag map */
+ tag_map.low =
+ readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_LOW);
+ tag_map.high =
+ readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_HIGH);
+ for (i = 0; i < 8; i++) {
+ bit = tag_map.full >> (8 * i);
+ ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
+ }
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 318e8a22d81..a52156e5688 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -32,6 +32,7 @@
#include <linux/dmaengine.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
#include "ioatdma.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
@@ -41,11 +42,23 @@
#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
+#define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80)
static int ioat_pending_level = 4;
module_param(ioat_pending_level, int, 0644);
MODULE_PARM_DESC(ioat_pending_level,
"high-water mark for pushing ioat descriptors (default: 4)");
+#define RESET_DELAY msecs_to_jiffies(100)
+#define WATCHDOG_DELAY round_jiffies(msecs_to_jiffies(2000))
+static void ioat_dma_chan_reset_part2(struct work_struct *work);
+static void ioat_dma_chan_watchdog(struct work_struct *work);
+
+/*
+ * workaround for IOAT ver.3.0 null descriptor issue
+ * (channel returns error when size is 0)
+ */
+#define NULL_DESC_BUFFER_SIZE 1
+
/* internal functions */
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
@@ -122,6 +135,38 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
int i;
struct ioat_dma_chan *ioat_chan;
+ /*
+ * IOAT ver.3 workarounds
+ */
+ if (device->version == IOAT_VER_3_0) {
+ u32 chan_err_mask;
+ u16 dev_id;
+ u32 dmauncerrsts;
+
+ /*
+ * Write CHANERRMSK_INT with 3E07h to mask out the errors
+ * that can cause stability issues for IOAT ver.3
+ */
+ chan_err_mask = 0x3E07;
+ pci_write_config_dword(device->pdev,
+ IOAT_PCI_CHANERRMASK_INT_OFFSET,
+ chan_err_mask);
+
+ /*
+ * Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
+ * (workaround for spurious config parity error after restart)
+ */
+ pci_read_config_word(device->pdev,
+ IOAT_PCI_DEVICE_ID_OFFSET,
+ &dev_id);
+ if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) {
+ dmauncerrsts = 0x10;
+ pci_write_config_dword(device->pdev,
+ IOAT_PCI_DMAUNCERRSTS_OFFSET,
+ dmauncerrsts);
+ }
+ }
+
device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
@@ -137,6 +182,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
ioat_chan->xfercap = xfercap;
ioat_chan->desccount = 0;
+ INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
if (ioat_chan->device->version != IOAT_VER_1_2) {
writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
| IOAT_DMA_DCA_ANY_CPU,
@@ -175,7 +221,7 @@ static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- if (ioat_chan->pending != 0) {
+ if (ioat_chan->pending > 0) {
spin_lock_bh(&ioat_chan->desc_lock);
__ioat1_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -194,13 +240,228 @@ static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- if (ioat_chan->pending != 0) {
+ if (ioat_chan->pending > 0) {
spin_lock_bh(&ioat_chan->desc_lock);
__ioat2_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
}
}
+
+/**
+ * ioat_dma_chan_reset_part2 - reinit the channel after a reset
+ */
+static void ioat_dma_chan_reset_part2(struct work_struct *work)
+{
+ struct ioat_dma_chan *ioat_chan =
+ container_of(work, struct ioat_dma_chan, work.work);
+ struct ioat_desc_sw *desc;
+
+ spin_lock_bh(&ioat_chan->cleanup_lock);
+ spin_lock_bh(&ioat_chan->desc_lock);
+
+ ioat_chan->completion_virt->low = 0;
+ ioat_chan->completion_virt->high = 0;
+ ioat_chan->pending = 0;
+
+ /*
+ * count the descriptors waiting, and be sure to do it
+ * right for both the CB1 line and the CB2 ring
+ */
+ ioat_chan->dmacount = 0;
+ if (ioat_chan->used_desc.prev) {
+ desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ do {
+ ioat_chan->dmacount++;
+ desc = to_ioat_desc(desc->node.next);
+ } while (&desc->node != ioat_chan->used_desc.next);
+ }
+
+ /*
+ * write the new starting descriptor address
+ * this puts channel engine into ARMED state
+ */
+ desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ break;
+ case IOAT_VER_2_0:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+ /* tell the engine to go with what's left to be done */
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+
+ break;
+ }
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d reset - %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
+
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_reset_channel - restart a channel
+ * @ioat_chan: IOAT DMA channel handle
+ */
+static void ioat_dma_reset_channel(struct ioat_dma_chan *ioat_chan)
+{
+ u32 chansts, chanerr;
+
+ if (!ioat_chan->used_desc.prev)
+ return;
+
+ chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ chansts = (ioat_chan->completion_virt->low
+ & IOAT_CHANSTS_DMA_TRANSFER_STATUS);
+ if (chanerr) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",
+ chan_num(ioat_chan), chansts, chanerr);
+ writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+ }
+
+ /*
+ * whack it upside the head with a reset
+ * and wait for things to settle out.
+ * force the pending count to a really big negative
+ * to make sure no one forces an issue_pending
+ * while we're waiting.
+ */
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ ioat_chan->pending = INT_MIN;
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ /* schedule the 2nd half instead of sleeping a long time */
+ schedule_delayed_work(&ioat_chan->work, RESET_DELAY);
+}
+
+/**
+ * ioat_dma_chan_watchdog - watch for stuck channels
+ */
+static void ioat_dma_chan_watchdog(struct work_struct *work)
+{
+ struct ioatdma_device *device =
+ container_of(work, struct ioatdma_device, work.work);
+ struct ioat_dma_chan *ioat_chan;
+ int i;
+
+ union {
+ u64 full;
+ struct {
+ u32 low;
+ u32 high;
+ };
+ } completion_hw;
+ unsigned long compl_desc_addr_hw;
+
+ for (i = 0; i < device->common.chancnt; i++) {
+ ioat_chan = ioat_lookup_chan_by_index(device, i);
+
+ if (ioat_chan->device->version == IOAT_VER_1_2
+ /* have we started processing anything yet */
+ && ioat_chan->last_completion
+ /* have we completed any since last watchdog cycle? */
+ && (ioat_chan->last_completion ==
+ ioat_chan->watchdog_completion)
+ /* has TCP stuck on one cookie since last watchdog? */
+ && (ioat_chan->watchdog_tcp_cookie ==
+ ioat_chan->watchdog_last_tcp_cookie)
+ && (ioat_chan->watchdog_tcp_cookie !=
+ ioat_chan->completed_cookie)
+ /* is there something in the chain to be processed? */
+ /* CB1 chain always has at least the last one processed */
+ && (ioat_chan->used_desc.prev != ioat_chan->used_desc.next)
+ && ioat_chan->pending == 0) {
+
+ /*
+ * check CHANSTS register for completed
+ * descriptor address.
+ * if it is different than completion writeback,
+ * it is not zero
+ * and it has changed since the last watchdog
+ * we can assume that channel
+ * is still working correctly
+ * and the problem is in completion writeback.
+ * update completion writeback
+ * with actual CHANSTS value
+ * else
+ * try resetting the channel
+ */
+
+ completion_hw.low = readl(ioat_chan->reg_base +
+ IOAT_CHANSTS_OFFSET_LOW(ioat_chan->device->version));
+ completion_hw.high = readl(ioat_chan->reg_base +
+ IOAT_CHANSTS_OFFSET_HIGH(ioat_chan->device->version));
+#if (BITS_PER_LONG == 64)
+ compl_desc_addr_hw =
+ completion_hw.full
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+ compl_desc_addr_hw =
+ completion_hw.low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+ if ((compl_desc_addr_hw != 0)
+ && (compl_desc_addr_hw != ioat_chan->watchdog_completion)
+ && (compl_desc_addr_hw != ioat_chan->last_compl_desc_addr_hw)) {
+ ioat_chan->last_compl_desc_addr_hw = compl_desc_addr_hw;
+ ioat_chan->completion_virt->low = completion_hw.low;
+ ioat_chan->completion_virt->high = completion_hw.high;
+ } else {
+ ioat_dma_reset_channel(ioat_chan);
+ ioat_chan->watchdog_completion = 0;
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ }
+
+ /*
+ * for version 2.0 if there are descriptors yet to be processed
+ * and the last completed hasn't changed since the last watchdog
+ * if they haven't hit the pending level
+ * issue the pending to push them through
+ * else
+ * try resetting the channel
+ */
+ } else if (ioat_chan->device->version == IOAT_VER_2_0
+ && ioat_chan->used_desc.prev
+ && ioat_chan->last_completion
+ && ioat_chan->last_completion == ioat_chan->watchdog_completion) {
+
+ if (ioat_chan->pending < ioat_pending_level)
+ ioat2_dma_memcpy_issue_pending(&ioat_chan->common);
+ else {
+ ioat_dma_reset_channel(ioat_chan);
+ ioat_chan->watchdog_completion = 0;
+ }
+ } else {
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ ioat_chan->watchdog_completion
+ = ioat_chan->last_completion;
+ }
+
+ ioat_chan->watchdog_last_tcp_cookie =
+ ioat_chan->watchdog_tcp_cookie;
+ }
+
+ schedule_delayed_work(&device->work, WATCHDOG_DELAY);
+}
+
static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
@@ -250,6 +511,13 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
prev = new;
} while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
+ if (!new) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "tx submit failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return -ENOMEM;
+ }
+
hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
@@ -335,7 +603,14 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
desc_count++;
} while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
- hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (!new) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "tx submit failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return -ENOMEM;
+ }
+
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
if (first != new) {
@@ -406,6 +681,7 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
desc_sw->async_tx.tx_submit = ioat1_tx_submit;
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
desc_sw->async_tx.tx_submit = ioat2_tx_submit;
break;
}
@@ -452,7 +728,8 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
* ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
* @chan: the channel to be filled out
*/
-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
struct ioat_desc_sw *desc;
@@ -555,6 +832,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
}
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
list_for_each_entry_safe(desc, _desc,
ioat_chan->free_desc.next, node) {
list_del(&desc->node);
@@ -585,6 +863,10 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
ioat_chan->last_completion = ioat_chan->completion_addr = 0;
ioat_chan->pending = 0;
ioat_chan->dmacount = 0;
+ ioat_chan->watchdog_completion = 0;
+ ioat_chan->last_compl_desc_addr_hw = 0;
+ ioat_chan->watchdog_tcp_cookie =
+ ioat_chan->watchdog_last_tcp_cookie = 0;
}
/**
@@ -640,7 +922,8 @@ ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
/* set up the noop descriptor */
noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
- noop_desc->hw->size = 0;
+ /* set size to non-zero value (channel returns error when size is 0) */
+ noop_desc->hw->size = NULL_DESC_BUFFER_SIZE;
noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
noop_desc->hw->src_addr = 0;
noop_desc->hw->dst_addr = 0;
@@ -690,6 +973,7 @@ static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
return ioat1_dma_get_next_descriptor(ioat_chan);
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
return ioat2_dma_get_next_descriptor(ioat_chan);
break;
}
@@ -716,8 +1000,12 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
new->src = dma_src;
new->async_tx.flags = flags;
return &new->async_tx;
- } else
+ } else {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
return NULL;
+ }
}
static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
@@ -744,8 +1032,13 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
new->src = dma_src;
new->async_tx.flags = flags;
return &new->async_tx;
- } else
+ } else {
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ dev_err(&ioat_chan->device->pdev->dev,
+ "chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+ chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
return NULL;
+ }
}
static void ioat_dma_cleanup_tasklet(unsigned long data)
@@ -756,6 +1049,27 @@ static void ioat_dma_cleanup_tasklet(unsigned long data)
chan->reg_base + IOAT_CHANCTRL_OFFSET);
}
+static void
+ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)
+{
+ /*
+ * yes we are unmapping both _page and _single
+ * alloc'd regions with unmap_page. Is this
+ * *really* that bad?
+ */
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP))
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+
+ if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP))
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+}
+
/**
* ioat_dma_memcpy_cleanup - cleanup up finished descriptors
* @chan: ioat channel to be cleaned up
@@ -799,11 +1113,27 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
if (phys_complete == ioat_chan->last_completion) {
spin_unlock_bh(&ioat_chan->cleanup_lock);
+ /*
+ * perhaps we're stuck so hard that the watchdog can't go off?
+ * try to catch it after 2 seconds
+ */
+ if (ioat_chan->device->version != IOAT_VER_3_0) {
+ if (time_after(jiffies,
+ ioat_chan->last_completion_time + HZ*WATCHDOG_DELAY)) {
+ ioat_dma_chan_watchdog(&(ioat_chan->device->work.work));
+ ioat_chan->last_completion_time = jiffies;
+ }
+ }
return;
}
+ ioat_chan->last_completion_time = jiffies;
cookie = 0;
- spin_lock_bh(&ioat_chan->desc_lock);
+ if (!spin_trylock_bh(&ioat_chan->desc_lock)) {
+ spin_unlock_bh(&ioat_chan->cleanup_lock);
+ return;
+ }
+
switch (ioat_chan->device->version) {
case IOAT_VER_1_2:
list_for_each_entry_safe(desc, _desc,
@@ -816,21 +1146,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
*/
if (desc->async_tx.cookie) {
cookie = desc->async_tx.cookie;
-
- /*
- * yes we are unmapping both _page and _single
- * alloc'd regions with unmap_page. Is this
- * *really* that bad?
- */
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
-
+ ioat_dma_unmap(ioat_chan, desc);
if (desc->async_tx.callback) {
desc->async_tx.callback(desc->async_tx.callback_param);
desc->async_tx.callback = NULL;
@@ -862,6 +1178,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
}
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
/* has some other thread has already cleaned up? */
if (ioat_chan->used_desc.prev == NULL)
break;
@@ -889,16 +1206,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
if (desc->async_tx.cookie) {
cookie = desc->async_tx.cookie;
desc->async_tx.cookie = 0;
-
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
-
+ ioat_dma_unmap(ioat_chan, desc);
if (desc->async_tx.callback) {
desc->async_tx.callback(desc->async_tx.callback_param);
desc->async_tx.callback = NULL;
@@ -943,6 +1251,7 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
last_used = chan->cookie;
last_complete = ioat_chan->completed_cookie;
+ ioat_chan->watchdog_tcp_cookie = cookie;
if (done)
*done = last_complete;
@@ -973,10 +1282,19 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
spin_lock_bh(&ioat_chan->desc_lock);
desc = ioat_dma_get_next_descriptor(ioat_chan);
+
+ if (!desc) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "Unable to start null desc - get next desc failed\n");
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ return;
+ }
+
desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
| IOAT_DMA_DESCRIPTOR_CTL_INT_GN
| IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- desc->hw->size = 0;
+ /* set size to non-zero value (channel returns error when size is 0) */
+ desc->hw->size = NULL_DESC_BUFFER_SIZE;
desc->hw->src_addr = 0;
desc->hw->dst_addr = 0;
async_tx_ack(&desc->async_tx);
@@ -994,6 +1312,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
+ IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
writel(((u64) desc->async_tx.phys) >> 32,
@@ -1049,7 +1368,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
+ if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) {
dev_err(&device->pdev->dev,
"selftest cannot allocate chan resource\n");
err = -ENODEV;
@@ -1312,6 +1631,7 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
ioat1_dma_memcpy_issue_pending;
break;
case IOAT_VER_2_0:
+ case IOAT_VER_3_0:
device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
device->common.device_issue_pending =
ioat2_dma_memcpy_issue_pending;
@@ -1331,8 +1651,16 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
if (err)
goto err_self_test;
+ ioat_set_tcp_copy_break(device);
+
dma_async_device_register(&device->common);
+ if (device->version != IOAT_VER_3_0) {
+ INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog);
+ schedule_delayed_work(&device->work,
+ WATCHDOG_DELAY);
+ }
+
return device;
err_self_test:
@@ -1365,6 +1693,10 @@ void ioat_dma_remove(struct ioatdma_device *device)
pci_release_regions(device->pdev);
pci_disable_device(device->pdev);
+ if (device->version != IOAT_VER_3_0) {
+ cancel_delayed_work(&device->work);
+ }
+
list_for_each_entry_safe(chan, _chan,
&device->common.channels, device_node) {
ioat_chan = to_ioat_chan(chan);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index f2c7fedbf00..a3306d0e137 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -27,8 +27,9 @@
#include <linux/dmapool.h>
#include <linux/cache.h>
#include <linux/pci_ids.h>
+#include <net/tcp.h>
-#define IOAT_DMA_VERSION "2.04"
+#define IOAT_DMA_VERSION "3.30"
enum ioat_interrupt {
none = 0,
@@ -40,6 +41,7 @@ enum ioat_interrupt {
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
#define IOAT_DMA_DCA_ANY_CPU ~0
+#define IOAT_WATCHDOG_PERIOD (2 * HZ)
/**
@@ -62,6 +64,7 @@ struct ioatdma_device {
struct dma_device common;
u8 version;
enum ioat_interrupt irq_mode;
+ struct delayed_work work;
struct msix_entry msix_entries[4];
struct ioat_dma_chan *idx[4];
};
@@ -75,6 +78,7 @@ struct ioat_dma_chan {
dma_cookie_t completed_cookie;
unsigned long last_completion;
+ unsigned long last_completion_time;
size_t xfercap; /* XFERCAP register value expanded out */
@@ -82,6 +86,10 @@ struct ioat_dma_chan {
spinlock_t desc_lock;
struct list_head free_desc;
struct list_head used_desc;
+ unsigned long watchdog_completion;
+ int watchdog_tcp_cookie;
+ u32 watchdog_last_tcp_cookie;
+ struct delayed_work work;
int pending;
int dmacount;
@@ -98,6 +106,7 @@ struct ioat_dma_chan {
u32 high;
};
} *completion_virt;
+ unsigned long last_compl_desc_addr_hw;
struct tasklet_struct cleanup_task;
};
@@ -121,17 +130,34 @@ struct ioat_desc_sw {
struct dma_async_tx_descriptor async_tx;
};
+static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)
+{
+ #ifdef CONFIG_NET_DMA
+ switch (dev->version) {
+ case IOAT_VER_1_2:
+ case IOAT_VER_3_0:
+ sysctl_tcp_dma_copybreak = 4096;
+ break;
+ case IOAT_VER_2_0:
+ sysctl_tcp_dma_copybreak = 2048;
+ break;
+ }
+ #endif
+}
+
#if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE)
struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
void __iomem *iobase);
void ioat_dma_remove(struct ioatdma_device *device);
struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
#else
#define ioat_dma_probe(pdev, iobase) NULL
#define ioat_dma_remove(device) do { } while (0)
#define ioat_dca_init(pdev, iobase) NULL
#define ioat2_dca_init(pdev, iobase) NULL
+#define ioat3_dca_init(pdev, iobase) NULL
#endif
#endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index dd470fa91d8..f1ae2c776f7 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -35,6 +35,7 @@
#define IOAT_PCI_SID 0x8086
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
+#define IOAT_VER_3_0 0x30 /* Version 3.0 */
struct ioat_dma_descriptor {
uint32_t size;
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index 9832d7ebd93..827cb503cac 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -25,6 +25,10 @@
#define IOAT_PCI_DMACTRL_DMA_EN 0x00000001
#define IOAT_PCI_DMACTRL_MSI_EN 0x00000002
+#define IOAT_PCI_DEVICE_ID_OFFSET 0x02
+#define IOAT_PCI_DMAUNCERRSTS_OFFSET 0x148
+#define IOAT_PCI_CHANERRMASK_INT_OFFSET 0x184
+
/* MMIO Device Registers */
#define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */
@@ -149,7 +153,23 @@
#define IOAT_DCA_GREQID_VALID 0x20000000
#define IOAT_DCA_GREQID_LASTID 0x80000000
+#define IOAT3_CSI_CAPABILITY_OFFSET 0x08
+#define IOAT3_CSI_CAPABILITY_PREFETCH 0x1
+
+#define IOAT3_PCI_CAPABILITY_OFFSET 0x0A
+#define IOAT3_PCI_CAPABILITY_MEMWR 0x1
+
+#define IOAT3_CSI_CONTROL_OFFSET 0x0C
+#define IOAT3_CSI_CONTROL_PREFETCH 0x1
+
+#define IOAT3_PCI_CONTROL_OFFSET 0x0E
+#define IOAT3_PCI_CONTROL_MEMWR 0x1
+
+#define IOAT3_APICID_TAG_MAP_OFFSET 0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_LOW 0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_HIGH 0x14
+#define IOAT3_DCA_GREQID_OFFSET 0x02
#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 0ec0f431e6a..85bfeba4d85 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -82,17 +82,24 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
struct device *dev =
&iop_chan->device->pdev->dev;
u32 len = unmap->unmap_len;
- u32 src_cnt = unmap->unmap_src_cnt;
- dma_addr_t addr = iop_desc_get_dest_addr(unmap,
- iop_chan);
-
- dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
- while (src_cnt--) {
- addr = iop_desc_get_src_addr(unmap,
- iop_chan,
- src_cnt);
- dma_unmap_page(dev, addr, len,
- DMA_TO_DEVICE);
+ enum dma_ctrl_flags flags = desc->async_tx.flags;
+ u32 src_cnt;
+ dma_addr_t addr;
+
+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ addr = iop_desc_get_dest_addr(unmap, iop_chan);
+ dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ }
+
+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ src_cnt = unmap->unmap_src_cnt;
+ while (src_cnt--) {
+ addr = iop_desc_get_src_addr(unmap,
+ iop_chan,
+ src_cnt);
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
+ }
}
desc->group_head = NULL;
}
@@ -366,8 +373,8 @@ retry:
if (!retry++)
goto retry;
- /* try to free some slots if the allocation fails */
- tasklet_schedule(&iop_chan->irq_tasklet);
+ /* perform direct reclaim if the allocation fails */
+ __iop_adma_slot_cleanup(iop_chan);
return NULL;
}
@@ -443,8 +450,18 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
-/* returns the number of allocated descriptors */
-static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+/**
+ * iop_adma_alloc_chan_resources - returns the number of allocated descriptors
+ * @chan - allocate descriptor resources for this channel
+ * @client - current client requesting the channel be ready for requests
+ *
+ * Note: We keep the slots for 1 operation on iop_chan->chain at all times. To
+ * avoid deadlock, via async_xor, num_descs_in_pool must at a minimum be
+ * greater than 2x the number slots needed to satisfy a device->max_xor
+ * request.
+ * */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
{
char *hw_desc;
int idx;
@@ -838,7 +855,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
err = -ENODEV;
goto out;
}
@@ -936,7 +953,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
err = -ENODEV;
goto out;
}
@@ -1387,6 +1404,8 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
spin_unlock_bh(&iop_chan->lock);
}
+MODULE_ALIAS("platform:iop-adma");
+
static struct platform_driver iop_adma_driver = {
.probe = iop_adma_probe,
.remove = iop_adma_remove,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
new file mode 100644
index 00000000000..a4e4494663b
--- /dev/null
+++ b/drivers/dma/mv_xor.c
@@ -0,0 +1,1375 @@
+/*
+ * offload engine driver for the Marvell XOR engine
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <asm/plat-orion/mv_xor.h>
+#include "mv_xor.h"
+
+static void mv_xor_issue_pending(struct dma_chan *chan);
+
+#define to_mv_xor_chan(chan) \
+ container_of(chan, struct mv_xor_chan, common)
+
+#define to_mv_xor_device(dev) \
+ container_of(dev, struct mv_xor_device, common)
+
+#define to_mv_xor_slot(tx) \
+ container_of(tx, struct mv_xor_desc_slot, async_tx)
+
+static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+
+ hw_desc->status = (1 << 31);
+ hw_desc->phy_next_desc = 0;
+ hw_desc->desc_command = (1 << 31);
+}
+
+static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ return hw_desc->phy_dest_addr;
+}
+
+static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
+ int src_idx)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ return hw_desc->phy_src_addr[src_idx];
+}
+
+
+static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
+ u32 byte_count)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->byte_count = byte_count;
+}
+
+static void mv_desc_set_next_desc(struct mv_xor_desc_slot *desc,
+ u32 next_desc_addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ BUG_ON(hw_desc->phy_next_desc);
+ hw_desc->phy_next_desc = next_desc_addr;
+}
+
+static void mv_desc_clear_next_desc(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_next_desc = 0;
+}
+
+static void mv_desc_set_block_fill_val(struct mv_xor_desc_slot *desc, u32 val)
+{
+ desc->value = val;
+}
+
+static void mv_desc_set_dest_addr(struct mv_xor_desc_slot *desc,
+ dma_addr_t addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_dest_addr = addr;
+}
+
+static int mv_chan_memset_slot_count(size_t len)
+{
+ return 1;
+}
+
+#define mv_chan_memcpy_slot_count(c) mv_chan_memset_slot_count(c)
+
+static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc,
+ int index, dma_addr_t addr)
+{
+ struct mv_xor_desc *hw_desc = desc->hw_desc;
+ hw_desc->phy_src_addr[index] = addr;
+ if (desc->type == DMA_XOR)
+ hw_desc->desc_command |= (1 << index);
+}
+
+static u32 mv_chan_get_current_desc(struct mv_xor_chan *chan)
+{
+ return __raw_readl(XOR_CURR_DESC(chan));
+}
+
+static void mv_chan_set_next_descriptor(struct mv_xor_chan *chan,
+ u32 next_desc_addr)
+{
+ __raw_writel(next_desc_addr, XOR_NEXT_DESC(chan));
+}
+
+static void mv_chan_set_dest_pointer(struct mv_xor_chan *chan, u32 desc_addr)
+{
+ __raw_writel(desc_addr, XOR_DEST_POINTER(chan));
+}
+
+static void mv_chan_set_block_size(struct mv_xor_chan *chan, u32 block_size)
+{
+ __raw_writel(block_size, XOR_BLOCK_SIZE(chan));
+}
+
+static void mv_chan_set_value(struct mv_xor_chan *chan, u32 value)
+{
+ __raw_writel(value, XOR_INIT_VALUE_LOW(chan));
+ __raw_writel(value, XOR_INIT_VALUE_HIGH(chan));
+}
+
+static void mv_chan_unmask_interrupts(struct mv_xor_chan *chan)
+{
+ u32 val = __raw_readl(XOR_INTR_MASK(chan));
+ val |= XOR_INTR_MASK_VALUE << (chan->idx * 16);
+ __raw_writel(val, XOR_INTR_MASK(chan));
+}
+
+static u32 mv_chan_get_intr_cause(struct mv_xor_chan *chan)
+{
+ u32 intr_cause = __raw_readl(XOR_INTR_CAUSE(chan));
+ intr_cause = (intr_cause >> (chan->idx * 16)) & 0xFFFF;
+ return intr_cause;
+}
+
+static int mv_is_err_intr(u32 intr_cause)
+{
+ if (intr_cause & ((1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)))
+ return 1;
+
+ return 0;
+}
+
+static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
+{
+ u32 val = (1 << (1 + (chan->idx * 16)));
+ dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
+ __raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static void mv_xor_device_clear_err_status(struct mv_xor_chan *chan)
+{
+ u32 val = 0xFFFF0000 >> (chan->idx * 16);
+ __raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static int mv_can_chain(struct mv_xor_desc_slot *desc)
+{
+ struct mv_xor_desc_slot *chain_old_tail = list_entry(
+ desc->chain_node.prev, struct mv_xor_desc_slot, chain_node);
+
+ if (chain_old_tail->type != desc->type)
+ return 0;
+ if (desc->type == DMA_MEMSET)
+ return 0;
+
+ return 1;
+}
+
+static void mv_set_mode(struct mv_xor_chan *chan,
+ enum dma_transaction_type type)
+{
+ u32 op_mode;
+ u32 config = __raw_readl(XOR_CONFIG(chan));
+
+ switch (type) {
+ case DMA_XOR:
+ op_mode = XOR_OPERATION_MODE_XOR;
+ break;
+ case DMA_MEMCPY:
+ op_mode = XOR_OPERATION_MODE_MEMCPY;
+ break;
+ case DMA_MEMSET:
+ op_mode = XOR_OPERATION_MODE_MEMSET;
+ break;
+ default:
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error: unsupported operation %d.\n",
+ type);
+ BUG();
+ return;
+ }
+
+ config &= ~0x7;
+ config |= op_mode;
+ __raw_writel(config, XOR_CONFIG(chan));
+ chan->current_type = type;
+}
+
+static void mv_chan_activate(struct mv_xor_chan *chan)
+{
+ u32 activation;
+
+ dev_dbg(chan->device->common.dev, " activate chan.\n");
+ activation = __raw_readl(XOR_ACTIVATION(chan));
+ activation |= 0x1;
+ __raw_writel(activation, XOR_ACTIVATION(chan));
+}
+
+static char mv_chan_is_busy(struct mv_xor_chan *chan)
+{
+ u32 state = __raw_readl(XOR_ACTIVATION(chan));
+
+ state = (state >> 4) & 0x3;
+
+ return (state == 1) ? 1 : 0;
+}
+
+static int mv_chan_xor_slot_count(size_t len, int src_cnt)
+{
+ return 1;
+}
+
+/**
+ * mv_xor_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_free_slots(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *slot)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d slot %p\n",
+ __func__, __LINE__, slot);
+
+ slot->slots_per_op = 0;
+
+}
+
+/*
+ * mv_xor_start_new_chain - program the engine to operate on new chain headed by
+ * sw_desc
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_start_new_chain(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *sw_desc)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d: sw_desc %p\n",
+ __func__, __LINE__, sw_desc);
+ if (sw_desc->type != mv_chan->current_type)
+ mv_set_mode(mv_chan, sw_desc->type);
+
+ if (sw_desc->type == DMA_MEMSET) {
+ /* for memset requests we need to program the engine, no
+ * descriptors used.
+ */
+ struct mv_xor_desc *hw_desc = sw_desc->hw_desc;
+ mv_chan_set_dest_pointer(mv_chan, hw_desc->phy_dest_addr);
+ mv_chan_set_block_size(mv_chan, sw_desc->unmap_len);
+ mv_chan_set_value(mv_chan, sw_desc->value);
+ } else {
+ /* set the hardware chain */
+ mv_chan_set_next_descriptor(mv_chan, sw_desc->async_tx.phys);
+ }
+ mv_chan->pending += sw_desc->slot_cnt;
+ mv_xor_issue_pending(&mv_chan->common);
+}
+
+static dma_cookie_t
+mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
+ struct mv_xor_chan *mv_chan, dma_cookie_t cookie)
+{
+ BUG_ON(desc->async_tx.cookie < 0);
+
+ if (desc->async_tx.cookie > 0) {
+ cookie = desc->async_tx.cookie;
+
+ /* call the callback (must not sleep or submit new
+ * operations to this channel)
+ */
+ if (desc->async_tx.callback)
+ desc->async_tx.callback(
+ desc->async_tx.callback_param);
+
+ /* unmap dma addresses
+ * (unmap_single vs unmap_page?)
+ */
+ if (desc->group_head && desc->unmap_len) {
+ struct mv_xor_desc_slot *unmap = desc->group_head;
+ struct device *dev =
+ &mv_chan->device->pdev->dev;
+ u32 len = unmap->unmap_len;
+ enum dma_ctrl_flags flags = desc->async_tx.flags;
+ u32 src_cnt;
+ dma_addr_t addr;
+
+ if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+ addr = mv_desc_get_dest_addr(unmap);
+ dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ }
+
+ if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+ src_cnt = unmap->unmap_src_cnt;
+ while (src_cnt--) {
+ addr = mv_desc_get_src_addr(unmap,
+ src_cnt);
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
+ }
+ }
+ desc->group_head = NULL;
+ }
+ }
+
+ /* run dependent operations */
+ async_tx_run_dependencies(&desc->async_tx);
+
+ return cookie;
+}
+
+static int
+mv_xor_clean_completed_slots(struct mv_xor_chan *mv_chan)
+{
+ struct mv_xor_desc_slot *iter, *_iter;
+
+ dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+ list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+ completed_node) {
+
+ if (async_tx_test_ack(&iter->async_tx)) {
+ list_del(&iter->completed_node);
+ mv_xor_free_slots(mv_chan, iter);
+ }
+ }
+ return 0;
+}
+
+static int
+mv_xor_clean_slot(struct mv_xor_desc_slot *desc,
+ struct mv_xor_chan *mv_chan)
+{
+ dev_dbg(mv_chan->device->common.dev, "%s %d: desc %p flags %d\n",
+ __func__, __LINE__, desc, desc->async_tx.flags);
+ list_del(&desc->chain_node);
+ /* the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!async_tx_test_ack(&desc->async_tx)) {
+ /* move this slot to the completed_slots */
+ list_add_tail(&desc->completed_node, &mv_chan->completed_slots);
+ return 0;
+ }
+
+ mv_xor_free_slots(mv_chan, desc);
+ return 0;
+}
+
+static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+ struct mv_xor_desc_slot *iter, *_iter;
+ dma_cookie_t cookie = 0;
+ int busy = mv_chan_is_busy(mv_chan);
+ u32 current_desc = mv_chan_get_current_desc(mv_chan);
+ int seen_current = 0;
+
+ dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+ dev_dbg(mv_chan->device->common.dev, "current_desc %x\n", current_desc);
+ mv_xor_clean_completed_slots(mv_chan);
+
+ /* free completed slots from the chain starting with
+ * the oldest descriptor
+ */
+
+ list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+ chain_node) {
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+
+ /* do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /* stop the search if we reach the current descriptor and the
+ * channel is busy
+ */
+ if (iter->async_tx.phys == current_desc) {
+ seen_current = 1;
+ if (busy)
+ break;
+ }
+
+ cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie);
+
+ if (mv_xor_clean_slot(iter, mv_chan))
+ break;
+ }
+
+ if ((busy == 0) && !list_empty(&mv_chan->chain)) {
+ struct mv_xor_desc_slot *chain_head;
+ chain_head = list_entry(mv_chan->chain.next,
+ struct mv_xor_desc_slot,
+ chain_node);
+
+ mv_xor_start_new_chain(mv_chan, chain_head);
+ }
+
+ if (cookie > 0)
+ mv_chan->completed_cookie = cookie;
+}
+
+static void
+mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+ spin_lock_bh(&mv_chan->lock);
+ __mv_xor_slot_cleanup(mv_chan);
+ spin_unlock_bh(&mv_chan->lock);
+}
+
+static void mv_xor_tasklet(unsigned long data)
+{
+ struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
+ __mv_xor_slot_cleanup(chan);
+}
+
+static struct mv_xor_desc_slot *
+mv_xor_alloc_slots(struct mv_xor_chan *mv_chan, int num_slots,
+ int slots_per_op)
+{
+ struct mv_xor_desc_slot *iter, *_iter, *alloc_start = NULL;
+ LIST_HEAD(chain);
+ int slots_found, retry = 0;
+
+ /* start search from the last allocated descrtiptor
+ * if a contiguous allocation can not be found start searching
+ * from the beginning of the list
+ */
+retry:
+ slots_found = 0;
+ if (retry == 0)
+ iter = mv_chan->last_used;
+ else
+ iter = list_entry(&mv_chan->all_slots,
+ struct mv_xor_desc_slot,
+ slot_node);
+
+ list_for_each_entry_safe_continue(
+ iter, _iter, &mv_chan->all_slots, slot_node) {
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+ if (iter->slots_per_op) {
+ /* give up after finding the first busy slot
+ * on the second pass through the list
+ */
+ if (retry)
+ break;
+
+ slots_found = 0;
+ continue;
+ }
+
+ /* start the allocation if the slot is correctly aligned */
+ if (!slots_found++)
+ alloc_start = iter;
+
+ if (slots_found == num_slots) {
+ struct mv_xor_desc_slot *alloc_tail = NULL;
+ struct mv_xor_desc_slot *last_used = NULL;
+ iter = alloc_start;
+ while (num_slots) {
+ int i;
+
+ /* pre-ack all but the last descriptor */
+ async_tx_ack(&iter->async_tx);
+
+ list_add_tail(&iter->chain_node, &chain);
+ alloc_tail = iter;
+ iter->async_tx.cookie = 0;
+ iter->slot_cnt = num_slots;
+ iter->xor_check_result = NULL;
+ for (i = 0; i < slots_per_op; i++) {
+ iter->slots_per_op = slots_per_op - i;
+ last_used = iter;
+ iter = list_entry(iter->slot_node.next,
+ struct mv_xor_desc_slot,
+ slot_node);
+ }
+ num_slots -= slots_per_op;
+ }
+ alloc_tail->group_head = alloc_start;
+ alloc_tail->async_tx.cookie = -EBUSY;
+ list_splice(&chain, &alloc_tail->async_tx.tx_list);
+ mv_chan->last_used = last_used;
+ mv_desc_clear_next_desc(alloc_start);
+ mv_desc_clear_next_desc(alloc_tail);
+ return alloc_tail;
+ }
+ }
+ if (!retry++)
+ goto retry;
+
+ /* try to free some slots if the allocation fails */
+ tasklet_schedule(&mv_chan->irq_tasklet);
+
+ return NULL;
+}
+
+static dma_cookie_t
+mv_desc_assign_cookie(struct mv_xor_chan *mv_chan,
+ struct mv_xor_desc_slot *desc)
+{
+ dma_cookie_t cookie = mv_chan->common.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+ mv_chan->common.cookie = desc->async_tx.cookie = cookie;
+ return cookie;
+}
+
+/************************ DMA engine API functions ****************************/
+static dma_cookie_t
+mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct mv_xor_desc_slot *sw_desc = to_mv_xor_slot(tx);
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(tx->chan);
+ struct mv_xor_desc_slot *grp_start, *old_chain_tail;
+ dma_cookie_t cookie;
+ int new_hw_chain = 1;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p: async_tx %p\n",
+ __func__, sw_desc, &sw_desc->async_tx);
+
+ grp_start = sw_desc->group_head;
+
+ spin_lock_bh(&mv_chan->lock);
+ cookie = mv_desc_assign_cookie(mv_chan, sw_desc);
+
+ if (list_empty(&mv_chan->chain))
+ list_splice_init(&sw_desc->async_tx.tx_list, &mv_chan->chain);
+ else {
+ new_hw_chain = 0;
+
+ old_chain_tail = list_entry(mv_chan->chain.prev,
+ struct mv_xor_desc_slot,
+ chain_node);
+ list_splice_init(&grp_start->async_tx.tx_list,
+ &old_chain_tail->chain_node);
+
+ if (!mv_can_chain(grp_start))
+ goto submit_done;
+
+ dev_dbg(mv_chan->device->common.dev, "Append to last desc %x\n",
+ old_chain_tail->async_tx.phys);
+
+ /* fix up the hardware chain */
+ mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+ /* if the channel is not busy */
+ if (!mv_chan_is_busy(mv_chan)) {
+ u32 current_desc = mv_chan_get_current_desc(mv_chan);
+ /*
+ * and the curren desc is the end of the chain before
+ * the append, then we need to start the channel
+ */
+ if (current_desc == old_chain_tail->async_tx.phys)
+ new_hw_chain = 1;
+ }
+ }
+
+ if (new_hw_chain)
+ mv_xor_start_new_chain(mv_chan, grp_start);
+
+submit_done:
+ spin_unlock_bh(&mv_chan->lock);
+
+ return cookie;
+}
+
+/* returns the number of allocated descriptors */
+static int mv_xor_alloc_chan_resources(struct dma_chan *chan,
+ struct dma_client *client)
+{
+ char *hw_desc;
+ int idx;
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *slot = NULL;
+ struct mv_xor_platform_data *plat_data =
+ mv_chan->device->pdev->dev.platform_data;
+ int num_descs_in_pool = plat_data->pool_size/MV_XOR_SLOT_SIZE;
+
+ /* Allocate descriptor slots */
+ idx = mv_chan->slots_allocated;
+ while (idx < num_descs_in_pool) {
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ printk(KERN_INFO "MV XOR Channel only initialized"
+ " %d descriptor slots", idx);
+ break;
+ }
+ hw_desc = (char *) mv_chan->device->dma_desc_pool_virt;
+ slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+
+ dma_async_tx_descriptor_init(&slot->async_tx, chan);
+ slot->async_tx.tx_submit = mv_xor_tx_submit;
+ INIT_LIST_HEAD(&slot->chain_node);
+ INIT_LIST_HEAD(&slot->slot_node);
+ INIT_LIST_HEAD(&slot->async_tx.tx_list);
+ hw_desc = (char *) mv_chan->device->dma_desc_pool;
+ slot->async_tx.phys =
+ (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+ slot->idx = idx++;
+
+ spin_lock_bh(&mv_chan->lock);
+ mv_chan->slots_allocated = idx;
+ list_add_tail(&slot->slot_node, &mv_chan->all_slots);
+ spin_unlock_bh(&mv_chan->lock);
+ }
+
+ if (mv_chan->slots_allocated && !mv_chan->last_used)
+ mv_chan->last_used = list_entry(mv_chan->all_slots.next,
+ struct mv_xor_desc_slot,
+ slot_node);
+
+ dev_dbg(mv_chan->device->common.dev,
+ "allocated %d descriptor slots last_used: %p\n",
+ mv_chan->slots_allocated, mv_chan->last_used);
+
+ return mv_chan->slots_allocated ? : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s dest: %x src %x len: %u flags: %ld\n",
+ __func__, dest, src, len, flags);
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_memcpy_slot_count(len);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_MEMCPY;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ mv_desc_set_src_addr(grp_start, 0, src);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ }
+ spin_unlock_bh(&mv_chan->lock);
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p\n",
+ __func__, sw_desc, sw_desc ? &sw_desc->async_tx : 0);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
+ size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s dest: %x len: %u flags: %ld\n",
+ __func__, dest, len, flags);
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_memset_slot_count(len);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_MEMSET;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ mv_desc_set_block_fill_val(grp_start, value);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ }
+ spin_unlock_bh(&mv_chan->lock);
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p \n",
+ __func__, sw_desc, &sw_desc->async_tx);
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, size_t len, unsigned long flags)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *sw_desc, *grp_start;
+ int slot_cnt;
+
+ if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+ return NULL;
+
+ BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+ dev_dbg(mv_chan->device->common.dev,
+ "%s src_cnt: %d len: dest %x %u flags: %ld\n",
+ __func__, src_cnt, len, dest, flags);
+
+ spin_lock_bh(&mv_chan->lock);
+ slot_cnt = mv_chan_xor_slot_count(len, src_cnt);
+ sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+ if (sw_desc) {
+ sw_desc->type = DMA_XOR;
+ sw_desc->async_tx.flags = flags;
+ grp_start = sw_desc->group_head;
+ mv_desc_init(grp_start, flags);
+ /* the byte count field is the same as in memcpy desc*/
+ mv_desc_set_byte_count(grp_start, len);
+ mv_desc_set_dest_addr(sw_desc->group_head, dest);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
+ while (src_cnt--)
+ mv_desc_set_src_addr(grp_start, src_cnt, src[src_cnt]);
+ }
+ spin_unlock_bh(&mv_chan->lock);
+ dev_dbg(mv_chan->device->common.dev,
+ "%s sw_desc %p async_tx %p \n",
+ __func__, sw_desc, &sw_desc->async_tx);
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void mv_xor_free_chan_resources(struct dma_chan *chan)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ struct mv_xor_desc_slot *iter, *_iter;
+ int in_use_descs = 0;
+
+ mv_xor_slot_cleanup(mv_chan);
+
+ spin_lock_bh(&mv_chan->lock);
+ list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+ chain_node) {
+ in_use_descs++;
+ list_del(&iter->chain_node);
+ }
+ list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+ completed_node) {
+ in_use_descs++;
+ list_del(&iter->completed_node);
+ }
+ list_for_each_entry_safe_reverse(
+ iter, _iter, &mv_chan->all_slots, slot_node) {
+ list_del(&iter->slot_node);
+ kfree(iter);
+ mv_chan->slots_allocated--;
+ }
+ mv_chan->last_used = NULL;
+
+ dev_dbg(mv_chan->device->common.dev, "%s slots_allocated %d\n",
+ __func__, mv_chan->slots_allocated);
+ spin_unlock_bh(&mv_chan->lock);
+
+ if (in_use_descs)
+ dev_err(mv_chan->device->common.dev,
+ "freeing %d in use descriptors!\n", in_use_descs);
+}
+
+/**
+ * mv_xor_is_complete - poll the status of an XOR transaction
+ * @chan: XOR channel handle
+ * @cookie: XOR transaction identifier
+ */
+static enum dma_status mv_xor_is_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done,
+ dma_cookie_t *used)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ enum dma_status ret;
+
+ last_used = chan->cookie;
+ last_complete = mv_chan->completed_cookie;
+ mv_chan->is_complete_cookie = cookie;
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret == DMA_SUCCESS) {
+ mv_xor_clean_completed_slots(mv_chan);
+ return ret;
+ }
+ mv_xor_slot_cleanup(mv_chan);
+
+ last_used = chan->cookie;
+ last_complete = mv_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static void mv_dump_xor_regs(struct mv_xor_chan *chan)
+{
+ u32 val;
+
+ val = __raw_readl(XOR_CONFIG(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "config 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ACTIVATION(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "activation 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_INTR_CAUSE(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "intr cause 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_INTR_MASK(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "intr mask 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ERROR_CAUSE(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error cause 0x%08x.\n", val);
+
+ val = __raw_readl(XOR_ERROR_ADDR(chan));
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error addr 0x%08x.\n", val);
+}
+
+static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
+ u32 intr_cause)
+{
+ if (intr_cause & (1 << 4)) {
+ dev_dbg(chan->device->common.dev,
+ "ignore this error\n");
+ return;
+ }
+
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error on chan %d. intr cause 0x%08x.\n",
+ chan->idx, intr_cause);
+
+ mv_dump_xor_regs(chan);
+ BUG();
+}
+
+static irqreturn_t mv_xor_interrupt_handler(int irq, void *data)
+{
+ struct mv_xor_chan *chan = data;
+ u32 intr_cause = mv_chan_get_intr_cause(chan);
+
+ dev_dbg(chan->device->common.dev, "intr cause %x\n", intr_cause);
+
+ if (mv_is_err_intr(intr_cause))
+ mv_xor_err_interrupt_handler(chan, intr_cause);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+ mv_xor_device_clear_eoc_cause(chan);
+
+ return IRQ_HANDLED;
+}
+
+static void mv_xor_issue_pending(struct dma_chan *chan)
+{
+ struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+
+ if (mv_chan->pending >= MV_XOR_THRESHOLD) {
+ mv_chan->pending = 0;
+ mv_chan_activate(mv_chan);
+ }
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define MV_XOR_TEST_SIZE 2000
+
+static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+{
+ int i;
+ void *src, *dest;
+ dma_addr_t src_dma, dest_dma;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ struct dma_async_tx_descriptor *tx;
+ int err = 0;
+ struct mv_xor_chan *mv_chan;
+
+ src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+
+ dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+ if (!dest) {
+ kfree(src);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffer */
+ for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+ ((u8 *) src)[i] = (u8)i;
+
+ /* Start copy, using first DMA channel */
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ dest_dma = dma_map_single(dma_chan->device->dev, dest,
+ MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+
+ src_dma = dma_map_single(dma_chan->device->dev, src,
+ MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+
+ tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+ MV_XOR_TEST_SIZE, 0);
+ cookie = mv_xor_tx_submit(tx);
+ mv_xor_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(1);
+
+ if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ mv_chan = to_mv_xor_chan(dma_chan);
+ dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+ MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+ if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+free_resources:
+ mv_xor_free_chan_resources(dma_chan);
+out:
+ kfree(src);
+ kfree(dest);
+ return err;
+}
+
+#define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+mv_xor_xor_self_test(struct mv_xor_device *device)
+{
+ int i, src_idx;
+ struct page *dest;
+ struct page *xor_srcs[MV_XOR_NUM_SRC_TEST];
+ dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
+ dma_addr_t dest_dma;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ u8 cmp_byte = 0;
+ u32 cmp_word;
+ int err = 0;
+ struct mv_xor_chan *mv_chan;
+
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+ xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+ if (!xor_srcs[src_idx])
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+ }
+
+ dest = alloc_page(GFP_KERNEL);
+ if (!dest)
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffers */
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+ u8 *ptr = page_address(xor_srcs[src_idx]);
+ for (i = 0; i < PAGE_SIZE; i++)
+ ptr[i] = (1 << src_idx);
+ }
+
+ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+ cmp_byte ^= (u8) (1 << src_idx);
+
+ cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+ (cmp_byte << 8) | cmp_byte;
+
+ memset(page_address(dest), 0, PAGE_SIZE);
+
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ /* test xor */
+ dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+ DMA_FROM_DEVICE);
+
+ for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
+ dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+
+ tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+ MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+
+ cookie = mv_xor_tx_submit(tx);
+ mv_xor_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ mv_chan = to_mv_xor_chan(dma_chan);
+ dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+ u32 *ptr = page_address(dest);
+ if (ptr[i] != cmp_word) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor failed compare, disabling."
+ " index %d, data %x, expected %x\n", i,
+ ptr[i], cmp_word);
+ err = -ENODEV;
+ goto free_resources;
+ }
+ }
+
+free_resources:
+ mv_xor_free_chan_resources(dma_chan);
+out:
+ src_idx = MV_XOR_NUM_SRC_TEST;
+ while (src_idx--)
+ __free_page(xor_srcs[src_idx]);
+ __free_page(dest);
+ return err;
+}
+
+static int __devexit mv_xor_remove(struct platform_device *dev)
+{
+ struct mv_xor_device *device = platform_get_drvdata(dev);
+ struct dma_chan *chan, *_chan;
+ struct mv_xor_chan *mv_chan;
+ struct mv_xor_platform_data *plat_data = dev->dev.platform_data;
+
+ dma_async_device_unregister(&device->common);
+
+ dma_free_coherent(&dev->dev, plat_data->pool_size,
+ device->dma_desc_pool_virt, device->dma_desc_pool);
+
+ list_for_each_entry_safe(chan, _chan, &device->common.channels,
+ device_node) {
+ mv_chan = to_mv_xor_chan(chan);
+ list_del(&chan->device_node);
+ }
+
+ return 0;
+}
+
+static int __devinit mv_xor_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int irq;
+ struct mv_xor_device *adev;
+ struct mv_xor_chan *mv_chan;
+ struct dma_device *dma_dev;
+ struct mv_xor_platform_data *plat_data = pdev->dev.platform_data;
+
+
+ adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return -ENOMEM;
+
+ dma_dev = &adev->common;
+
+ /* allocate coherent memory for hardware descriptors
+ * note: writecombine gives slightly better performance, but
+ * requires that we explicitly flush the writes
+ */
+ adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+ plat_data->pool_size,
+ &adev->dma_desc_pool,
+ GFP_KERNEL);
+ if (!adev->dma_desc_pool_virt)
+ return -ENOMEM;
+
+ adev->id = plat_data->hw_id;
+
+ /* discover transaction capabilites from the platform data */
+ dma_dev->cap_mask = plat_data->cap_mask;
+ adev->pdev = pdev;
+ platform_set_drvdata(pdev, adev);
+
+ adev->shared = platform_get_drvdata(plat_data->shared);
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+
+ /* set base routines */
+ dma_dev->device_alloc_chan_resources = mv_xor_alloc_chan_resources;
+ dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
+ dma_dev->device_is_tx_complete = mv_xor_is_complete;
+ dma_dev->device_issue_pending = mv_xor_issue_pending;
+ dma_dev->dev = &pdev->dev;
+
+ /* set prep routines based on capability */
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memcpy = mv_xor_prep_dma_memcpy;
+ if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memset = mv_xor_prep_dma_memset;
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ dma_dev->max_xor = 8; ;
+ dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
+ }
+
+ mv_chan = devm_kzalloc(&pdev->dev, sizeof(*mv_chan), GFP_KERNEL);
+ if (!mv_chan) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
+ mv_chan->device = adev;
+ mv_chan->idx = plat_data->hw_id;
+ mv_chan->mmr_base = adev->shared->xor_base;
+
+ if (!mv_chan->mmr_base) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
+ tasklet_init(&mv_chan->irq_tasklet, mv_xor_tasklet, (unsigned long)
+ mv_chan);
+
+ /* clear errors before enabling interrupts */
+ mv_xor_device_clear_err_status(mv_chan);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto err_free_dma;
+ }
+ ret = devm_request_irq(&pdev->dev, irq,
+ mv_xor_interrupt_handler,
+ 0, dev_name(&pdev->dev), mv_chan);
+ if (ret)
+ goto err_free_dma;
+
+ mv_chan_unmask_interrupts(mv_chan);
+
+ mv_set_mode(mv_chan, DMA_MEMCPY);
+
+ spin_lock_init(&mv_chan->lock);
+ INIT_LIST_HEAD(&mv_chan->chain);
+ INIT_LIST_HEAD(&mv_chan->completed_slots);
+ INIT_LIST_HEAD(&mv_chan->all_slots);
+ INIT_RCU_HEAD(&mv_chan->common.rcu);
+ mv_chan->common.device = dma_dev;
+
+ list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
+
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+ ret = mv_xor_memcpy_self_test(adev);
+ dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+ if (ret)
+ goto err_free_dma;
+ }
+
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ ret = mv_xor_xor_self_test(adev);
+ dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+ if (ret)
+ goto err_free_dma;
+ }
+
+ dev_printk(KERN_INFO, &pdev->dev, "Marvell XOR: "
+ "( %s%s%s%s)\n",
+ dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+ dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "",
+ dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+ dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+ dma_async_device_register(dma_dev);
+ goto out;
+
+ err_free_dma:
+ dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+ adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ out:
+ return ret;
+}
+
+static void
+mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
+ struct mbus_dram_target_info *dram)
+{
+ void __iomem *base = msp->xor_base;
+ u32 win_enable = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ writel(0, base + WINDOW_BASE(i));
+ writel(0, base + WINDOW_SIZE(i));
+ if (i < 4)
+ writel(0, base + WINDOW_REMAP_HIGH(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ writel((cs->base & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id, base + WINDOW_BASE(i));
+ writel((cs->size - 1) & 0xffff0000, base + WINDOW_SIZE(i));
+
+ win_enable |= (1 << i);
+ win_enable |= 3 << (16 + (2 * i));
+ }
+
+ writel(win_enable, base + WINDOW_BAR_ENABLE(0));
+ writel(win_enable, base + WINDOW_BAR_ENABLE(1));
+}
+
+static struct platform_driver mv_xor_driver = {
+ .probe = mv_xor_probe,
+ .remove = mv_xor_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MV_XOR_NAME,
+ },
+};
+
+static int mv_xor_shared_probe(struct platform_device *pdev)
+{
+ struct mv_xor_platform_shared_data *msd = pdev->dev.platform_data;
+ struct mv_xor_shared_private *msp;
+ struct resource *res;
+
+ dev_printk(KERN_NOTICE, &pdev->dev, "Marvell shared XOR driver\n");
+
+ msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
+ if (!msp)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ msp->xor_base = devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!msp->xor_base)
+ return -EBUSY;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start + 1);
+ if (!msp->xor_high_base)
+ return -EBUSY;
+
+ platform_set_drvdata(pdev, msp);
+
+ /*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (msd != NULL && msd->dram != NULL)
+ mv_xor_conf_mbus_windows(msp, msd->dram);
+
+ return 0;
+}
+
+static int mv_xor_shared_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver mv_xor_shared_driver = {
+ .probe = mv_xor_shared_probe,
+ .remove = mv_xor_shared_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MV_XOR_SHARED_NAME,
+ },
+};
+
+
+static int __init mv_xor_init(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&mv_xor_shared_driver);
+ if (!rc) {
+ rc = platform_driver_register(&mv_xor_driver);
+ if (rc)
+ platform_driver_unregister(&mv_xor_shared_driver);
+ }
+ return rc;
+}
+module_init(mv_xor_init);
+
+/* it's currently unsafe to unload this module */
+#if 0
+static void __exit mv_xor_exit(void)
+{
+ platform_driver_unregister(&mv_xor_driver);
+ platform_driver_unregister(&mv_xor_shared_driver);
+ return;
+}
+
+module_exit(mv_xor_exit);
+#endif
+
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_DESCRIPTION("DMA engine driver for Marvell's XOR engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
new file mode 100644
index 00000000000..06cafe1ef52
--- /dev/null
+++ b/drivers/dma/mv_xor.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MV_XOR_H
+#define MV_XOR_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define USE_TIMER
+#define MV_XOR_SLOT_SIZE 64
+#define MV_XOR_THRESHOLD 1
+
+#define XOR_OPERATION_MODE_XOR 0
+#define XOR_OPERATION_MODE_MEMCPY 2
+#define XOR_OPERATION_MODE_MEMSET 4
+
+#define XOR_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4))
+#define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (chan->idx * 4))
+#define XOR_BYTE_COUNT(chan) (chan->mmr_base + 0x220 + (chan->idx * 4))
+#define XOR_DEST_POINTER(chan) (chan->mmr_base + 0x2B0 + (chan->idx * 4))
+#define XOR_BLOCK_SIZE(chan) (chan->mmr_base + 0x2C0 + (chan->idx * 4))
+#define XOR_INIT_VALUE_LOW(chan) (chan->mmr_base + 0x2E0)
+#define XOR_INIT_VALUE_HIGH(chan) (chan->mmr_base + 0x2E4)
+
+#define XOR_CONFIG(chan) (chan->mmr_base + 0x10 + (chan->idx * 4))
+#define XOR_ACTIVATION(chan) (chan->mmr_base + 0x20 + (chan->idx * 4))
+#define XOR_INTR_CAUSE(chan) (chan->mmr_base + 0x30)
+#define XOR_INTR_MASK(chan) (chan->mmr_base + 0x40)
+#define XOR_ERROR_CAUSE(chan) (chan->mmr_base + 0x50)
+#define XOR_ERROR_ADDR(chan) (chan->mmr_base + 0x60)
+#define XOR_INTR_MASK_VALUE 0x3F5
+
+#define WINDOW_BASE(w) (0x250 + ((w) << 2))
+#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
+#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
+#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
+
+struct mv_xor_shared_private {
+ void __iomem *xor_base;
+ void __iomem *xor_high_base;
+};
+
+
+/**
+ * struct mv_xor_device - internal representation of a XOR device
+ * @pdev: Platform device
+ * @id: HW XOR Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct mv_xor_device {
+ struct platform_device *pdev;
+ int id;
+ dma_addr_t dma_desc_pool;
+ void *dma_desc_pool_virt;
+ struct dma_device common;
+ struct mv_xor_shared_private *shared;
+};
+
+/**
+ * struct mv_xor_chan - internal representation of a XOR channel
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the descriptors pool
+ * @mmr_base: memory mapped register base
+ * @idx: the index of the xor channel
+ * @chain: device chain view of the descriptors
+ * @completed_slots: slots completed by HW but still need to be acked
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where mv_xor_slot_cleanup runs
+ */
+struct mv_xor_chan {
+ int pending;
+ dma_cookie_t completed_cookie;
+ spinlock_t lock; /* protects the descriptor slot pool */
+ void __iomem *mmr_base;
+ unsigned int idx;
+ enum dma_transaction_type current_type;
+ struct list_head chain;
+ struct list_head completed_slots;
+ struct mv_xor_device *device;
+ struct dma_chan common;
+ struct mv_xor_desc_slot *last_used;
+ struct list_head all_slots;
+ int slots_allocated;
+ struct tasklet_struct irq_tasklet;
+#ifdef USE_TIMER
+ unsigned long cleanup_time;
+ u32 current_on_last_cleanup;
+ dma_cookie_t is_complete_cookie;
+#endif
+};
+
+/**
+ * struct mv_xor_desc_slot - software descriptor
+ * @slot_node: node on the mv_xor_chan.all_slots list
+ * @chain_node: node on the mv_xor_chan.chain list
+ * @completed_node: node on the mv_xor_chan.completed_slots list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ * for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct mv_xor_desc_slot {
+ struct list_head slot_node;
+ struct list_head chain_node;
+ struct list_head completed_node;
+ enum dma_transaction_type type;
+ void *hw_desc;
+ struct mv_xor_desc_slot *group_head;
+ u16 slot_cnt;
+ u16 slots_per_op;
+ u16 idx;
+ u16 unmap_src_cnt;
+ u32 value;
+ size_t unmap_len;
+ struct dma_async_tx_descriptor async_tx;
+ union {
+ u32 *xor_check_result;
+ u32 *crc32_result;
+ };
+#ifdef USE_TIMER
+ unsigned long arrival_time;
+ struct timer_list timeout;
+#endif
+};
+
+/* This structure describes XOR descriptor size 64bytes */
+struct mv_xor_desc {
+ u32 status; /* descriptor execution status */
+ u32 crc32_result; /* result of CRC-32 calculation */
+ u32 desc_command; /* type of operation to be carried out */
+ u32 phy_next_desc; /* next descriptor address pointer */
+ u32 byte_count; /* size of src/dst blocks in bytes */
+ u32 phy_dest_addr; /* destination block address */
+ u32 phy_src_addr[8]; /* source block addresses */
+ u32 reserved0;
+ u32 reserved1;
+};
+
+#define to_mv_sw_desc(addr_hw_desc) \
+ container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
+
+#define mv_hw_desc_slot_idx(hw_desc, idx) \
+ ((void *)(((unsigned long)hw_desc) + ((idx) << 5)))
+
+#define MV_XOR_MIN_BYTE_COUNT (128)
+#define XOR_MAX_BYTE_COUNT ((16 * 1024 * 1024) - 1)
+#define MV_XOR_MAX_BYTE_COUNT XOR_MAX_BYTE_COUNT
+
+
+#endif
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index b54112ffd28..0e024fe2d8c 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -33,7 +33,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
{
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = &mci->csrows[0];
- unsigned long address, pfn, offset;
+ unsigned long address, pfn, offset, syndrome;
dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
priv->node, chan, ar);
@@ -44,10 +44,11 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
address = (address << 1) | chan;
pfn = address >> PAGE_SHIFT;
offset = address & ~PAGE_MASK;
+ syndrome = (ar & 0x000000001fe00000ul) >> 21;
/* TODO: Decoding of the error addresss */
edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
- 0, 0, chan, "");
+ syndrome, 0, chan, "");
}
static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
diff --git a/drivers/eisa/Makefile b/drivers/eisa/Makefile
index 70abf93fe6b..5369ce957c6 100644
--- a/drivers/eisa/Makefile
+++ b/drivers/eisa/Makefile
@@ -9,7 +9,7 @@ obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
# Ugly hack to get DEVICE_NAME_SIZE value...
-DEVICE_NAME_SIZE =$(shell awk '$$1=="\#define" && $$2=="DEVICE_NAME_SIZE" {print $$3-1}' $(srctree)/include/linux/device.h)
+DEVICE_NAME_SIZE = 50
$(obj)/eisa-bus.o: $(obj)/devlist.h
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 65dcf043265..c950bf8606d 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -22,7 +22,7 @@
struct eisa_device_info {
struct eisa_device_id id;
- char name[DEVICE_NAME_SIZE];
+ char name[50];
};
#ifdef CONFIG_EISA_NAMES
@@ -63,7 +63,7 @@ static void __init eisa_name_device (struct eisa_device *edev)
if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) {
strlcpy (edev->pretty_name,
eisa_table[i].name,
- DEVICE_NAME_SIZE);
+ sizeof(edev->pretty_name));
return;
}
}
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 25918f7dfd0..0b624e927a6 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -254,6 +254,7 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
static int smi_request(struct smi_cmd *smi_cmd)
{
cpumask_t old_mask;
+ cpumask_of_cpu_ptr(new_mask, 0);
int ret = 0;
if (smi_cmd->magic != SMI_CMD_MAGIC) {
@@ -264,7 +265,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
/* SMI requires CPU 0 */
old_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
+ set_cpus_allowed_ptr(current, new_mask);
if (smp_processor_id() != 0) {
dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
__func__);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 008c38ba774..fced1909cbb 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -45,7 +45,7 @@ config GPIO_PCA953X
will be called pca953x.
config GPIO_PCF857X
- tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
+ tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C
help
Say yes here to provide access to most "quasi-bidirectional" I2C
@@ -54,7 +54,8 @@ config GPIO_PCF857X
some of them. Compatible models include:
8 bits: pcf8574, pcf8574a, pca8574, pca8574a,
- pca9670, pca9672, pca9674, pca9674a
+ pca9670, pca9672, pca9674, pca9674a,
+ max7328, max7329
16 bits: pcf8575, pcf8575c, pca8575,
pca9671, pca9673, pca9675
@@ -69,6 +70,12 @@ config GPIO_PCF857X
comment "SPI GPIO expanders:"
+config GPIO_MAX7301
+ tristate "Maxim MAX7301 GPIO expander"
+ depends on SPI_MASTER
+ help
+ gpio driver for Maxim MAX7301 SPI GPIO expander.
+
config GPIO_MCP23S08
tristate "Microchip MCP23S08 I/O expander"
depends on SPI_MASTER
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fdde9923cf3..16e796dc541 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o
+obj-$(CONFIG_GPIO_MAX7301) += max7301.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
new file mode 100644
index 00000000000..39c795ad831
--- /dev/null
+++ b/drivers/gpio/max7301.c
@@ -0,0 +1,339 @@
+/**
+ * drivers/gpio/max7301.c
+ *
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = databyte, D8..D14 = commandbyte
+ * - D15 = low -> write command
+ * - when reading
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = dummy, D8..D14 = register address
+ * - D15 = high -> read command
+ * - raise CS and assert it again
+ * - always clock in 16 clocks at once
+ * - at DOUT: D15 first, D0 last
+ * - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+
+#define DRIVER_NAME "max7301"
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct max7301 {
+ struct mutex lock;
+ u8 port_config[8]; /* field 0 is unused */
+ u32 out_level; /* cached output levels */
+ struct gpio_chip chip;
+ struct spi_device *spi;
+};
+
+/**
+ * max7301_write - Write a new register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ * @val: Value to write
+ *
+ * A write to the MAX7301 means one message with one transfer
+ *
+ * Returns 0 if successful or a negative value on error
+ */
+static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
+{
+ u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+ return spi_write(spi, (const u8 *)&word, sizeof(word));
+}
+
+/**
+ * max7301_read - Read back register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ *
+ * A read from the MAX7301 means two transfers; here, one message each
+ *
+ * Returns positive 8 bit value from device if successful or a
+ * negative value on error
+ */
+static int max7301_read(struct spi_device *spi, unsigned int reg)
+{
+ int ret;
+ u16 word;
+
+ word = 0x8000 | (reg << 8);
+ ret = spi_write(spi, (const u8 *)&word, sizeof(word));
+ if (ret)
+ return ret;
+ /*
+ * This relies on the fact, that a transfer with NULL tx_buf shifts out
+ * zero bytes (=NOOP for MAX7301)
+ */
+ ret = spi_read(spi, (u8 *)&word, sizeof(word));
+ if (ret)
+ return ret;
+ return word & 0xff;
+}
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ /* Standard GPIO API doesn't support pull-ups, has to be extended.
+ * Hard-coding no pollup for now. */
+ *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+ ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+ if (value) {
+ ts->out_level |= 1 << offset;
+ return max7301_write(ts->spi, 0x20 + offset, 0x01);
+ } else {
+ ts->out_level &= ~(1 << offset);
+ return max7301_write(ts->spi, 0x20 + offset, 0x00);
+ }
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+ ret = __max7301_set(ts, offset, value);
+
+ if (!ret)
+ ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ int config, level = -EINVAL;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
+
+ switch (config) {
+ case 1:
+ /* Output: return cached level */
+ level = !!(ts->out_level & (1 << offset));
+ break;
+ case 2:
+ case 3:
+ /* Input: read out */
+ level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
+ }
+ mutex_unlock(&ts->lock);
+
+ return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ __max7301_set(ts, offset, value);
+
+ mutex_unlock(&ts->lock);
+}
+
+static int __devinit max7301_probe(struct spi_device *spi)
+{
+ struct max7301 *ts;
+ struct max7301_platform_data *pdata;
+ int i, ret;
+
+ pdata = spi->dev.platform_data;
+ if (!pdata || !pdata->base)
+ return -ENODEV;
+
+ /*
+ * bits_per_word cannot be configured in platform data
+ */
+ spi->bits_per_word = 16;
+
+ ret = spi_setup(spi);
+ if (ret < 0)
+ return ret;
+
+ ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ mutex_init(&ts->lock);
+
+ dev_set_drvdata(&spi->dev, ts);
+
+ /* Power up the chip and disable IRQ output */
+ max7301_write(spi, 0x04, 0x01);
+
+ ts->spi = spi;
+
+ ts->chip.label = DRIVER_NAME,
+
+ ts->chip.direction_input = max7301_direction_input;
+ ts->chip.get = max7301_get;
+ ts->chip.direction_output = max7301_direction_output;
+ ts->chip.set = max7301_set;
+
+ ts->chip.base = pdata->base;
+ ts->chip.ngpio = PIN_NUMBER;
+ ts->chip.can_sleep = 1;
+ ts->chip.dev = &spi->dev;
+ ts->chip.owner = THIS_MODULE;
+
+ ret = gpiochip_add(&ts->chip);
+ if (ret)
+ goto exit_destroy;
+
+ /*
+ * tristate all pins in hardware and cache the
+ * register values for later use.
+ */
+ for (i = 1; i < 8; i++) {
+ int j;
+ /* 0xAA means input with internal pullup disabled */
+ max7301_write(spi, 0x08 + i, 0xAA);
+ ts->port_config[i] = 0xAA;
+ for (j = 0; j < 4; j++) {
+ int idx = ts->chip.base + (i - 1) * 4 + j;
+ ret = gpio_direction_input(idx);
+ if (ret)
+ goto exit_remove;
+ gpio_free(idx);
+ }
+ }
+ return ret;
+
+exit_remove:
+ gpiochip_remove(&ts->chip);
+exit_destroy:
+ dev_set_drvdata(&spi->dev, NULL);
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ return ret;
+}
+
+static int max7301_remove(struct spi_device *spi)
+{
+ struct max7301 *ts;
+ int ret;
+
+ ts = dev_get_drvdata(&spi->dev);
+ if (ts == NULL)
+ return -ENODEV;
+
+ dev_set_drvdata(&spi->dev, NULL);
+
+ /* Power down the chip and disable IRQ output */
+ max7301_write(spi, 0x04, 0x00);
+
+ ret = gpiochip_remove(&ts->chip);
+ if (!ret) {
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ } else
+ dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+ ret);
+
+ return ret;
+}
+
+static struct spi_driver max7301_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = max7301_probe,
+ .remove = __devexit_p(max7301_remove),
+};
+
+static int __init max7301_init(void)
+{
+ return spi_register_driver(&max7301_driver);
+}
+
+static void __exit max7301_exit(void)
+{
+ spi_unregister_driver(&max7301_driver);
+}
+
+module_init(max7301_init);
+module_exit(max7301_exit);
+
+MODULE_AUTHOR("Juergen Beisert");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index aa6cc8b2a2b..d25d356c4f2 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -37,6 +37,8 @@ static const struct i2c_device_id pcf857x_id[] = {
{ "pca9671", 16 },
{ "pca9673", 16 },
{ "pca9675", 16 },
+ { "max7328", 8 },
+ { "max7329", 8 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(i2c, pcf857x_id);
struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
+ struct mutex lock; /* protect 'out' */
unsigned out; /* software latch */
};
@@ -66,9 +69,14 @@ struct pcf857x {
static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+ int status;
+ mutex_lock(&gpio->lock);
gpio->out |= (1 << offset);
- return i2c_smbus_write_byte(gpio->client, gpio->out);
+ status = i2c_smbus_write_byte(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
@@ -84,12 +92,17 @@ static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
unsigned bit = 1 << offset;
+ int status;
+ mutex_lock(&gpio->lock);
if (value)
gpio->out |= bit;
else
gpio->out &= ~bit;
- return i2c_smbus_write_byte(gpio->client, gpio->out);
+ status = i2c_smbus_write_byte(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
@@ -124,9 +137,14 @@ static int i2c_read_le16(struct i2c_client *client)
static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+ int status;
+ mutex_lock(&gpio->lock);
gpio->out |= (1 << offset);
- return i2c_write_le16(gpio->client, gpio->out);
+ status = i2c_write_le16(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
@@ -142,12 +160,17 @@ static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
unsigned bit = 1 << offset;
+ int status;
+ mutex_lock(&gpio->lock);
if (value)
gpio->out |= bit;
else
gpio->out &= ~bit;
- return i2c_write_le16(gpio->client, gpio->out);
+ status = i2c_write_le16(gpio->client, gpio->out);
+ mutex_unlock(&gpio->lock);
+
+ return status;
}
static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
@@ -173,6 +196,8 @@ static int pcf857x_probe(struct i2c_client *client,
if (!gpio)
return -ENOMEM;
+ mutex_init(&gpio->lock);
+
gpio->chip.base = pdata->gpio_base;
gpio->chip.can_sleep = 1;
gpio->chip.owner = THIS_MODULE;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f43d6d3cf2f..426ac5add58 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -780,7 +780,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
*/
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
{
- __le64 x;
+ u64 x;
u64 m = (1ULL << n) - 1;
if (n > 32)
@@ -796,10 +796,10 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
report += offset >> 3;
offset &= 7;
- x = get_unaligned((__le64 *)report);
- x &= cpu_to_le64(~(m << offset));
- x |= cpu_to_le64(((u64) value) << offset);
- put_unaligned(x, (__le64 *) report);
+ x = get_unaligned_le64(report);
+ x &= ~(m << offset);
+ x |= ((u64)value) << offset;
+ put_unaligned_le64(x, report);
}
/*
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 4c2052c658f..16feea01449 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -89,6 +89,29 @@ static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_de
return 1;
}
+static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+ return 0;
+
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ /* Reported on Gyration MCE Remote */
+ case 0x00d: map_key_clear(KEY_HOME); break;
+ case 0x024: map_key_clear(KEY_DVD); break;
+ case 0x025: map_key_clear(KEY_PVR); break;
+ case 0x046: map_key_clear(KEY_MEDIA); break;
+ case 0x047: map_key_clear(KEY_MP3); break;
+ case 0x049: map_key_clear(KEY_CAMERA); break;
+ case 0x04a: map_key_clear(KEY_VIDEO); break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
unsigned long **bit, int *max)
{
@@ -303,6 +326,9 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *inp
#define VENDOR_ID_EZKEY 0x0518
#define DEVICE_ID_BTC_8193 0x0002
+#define VENDOR_ID_GYRATION 0x0c16
+#define DEVICE_ID_GYRATION_REMOTE 0x0002
+
#define VENDOR_ID_LOGITECH 0x046d
#define DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define DEVICE_ID_S510_RECEIVER 0xc50c
@@ -337,6 +363,8 @@ static const struct hid_input_blacklist {
{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
+ { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },
+
{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
@@ -438,6 +466,18 @@ int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struc
input_event(input, usage->type, REL_WHEEL, -value);
return 1;
}
+
+ /* Gyration MCE remote "Sleep" key */
+ if (hid->vendor == VENDOR_ID_GYRATION &&
+ hid->product == DEVICE_ID_GYRATION_REMOTE &&
+ (usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+ (usage->hid & 0xff) == 0x82) {
+ input_event(input, usage->type, usage->code, 1);
+ input_sync(input);
+ input_event(input, usage->type, usage->code, 0);
+ input_sync(input);
+ return 1;
+ }
return 0;
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5c52a20ad34..1b2e8dc3398 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -100,6 +100,8 @@ static struct hidinput_key_translation apple_fn_keys[] = {
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
{ KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */
{ KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
+ { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
+ { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
{ KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
{ KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
{ KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
@@ -612,6 +614,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
case 0x0b7: map_key_clear(KEY_STOPCD); break;
case 0x0b8: map_key_clear(KEY_EJECTCD); break;
+ case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break;
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 2fde6c63f47..c40f0403eda 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -105,6 +105,7 @@ out:
static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ /* FIXME: What stops hidraw_table going NULL */
struct hid_device *dev = hidraw_table[minor]->hid;
__u8 *buf;
int ret = 0;
@@ -211,38 +212,43 @@ static int hidraw_release(struct inode * inode, struct file * file)
kfree(list->hidraw);
}
+ kfree(list);
+
return 0;
}
-static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hidraw_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
+ struct inode *inode = file->f_path.dentry->d_inode;
unsigned int minor = iminor(inode);
+ long ret = 0;
+ /* FIXME: What stops hidraw_table going NULL */
struct hidraw *dev = hidraw_table[minor];
void __user *user_arg = (void __user*) arg;
+ lock_kernel();
switch (cmd) {
case HIDIOCGRDESCSIZE:
if (put_user(dev->hid->rsize, (int __user *)arg))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ break;
case HIDIOCGRDESC:
{
__u32 len;
if (get_user(len, (int __user *)arg))
- return -EFAULT;
-
- if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
- return -EINVAL;
-
- if (copy_to_user(user_arg + offsetof(
- struct hidraw_report_descriptor,
- value[0]),
- dev->hid->rdesc,
- min(dev->hid->rsize, len)))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+ ret = -EINVAL;
+ else if (copy_to_user(user_arg + offsetof(
+ struct hidraw_report_descriptor,
+ value[0]),
+ dev->hid->rdesc,
+ min(dev->hid->rsize, len)))
+ ret = -EFAULT;
+ break;
}
case HIDIOCGRAWINFO:
{
@@ -252,15 +258,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.vendor = dev->hid->vendor;
dinfo.product = dev->hid->product;
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
- return -EFAULT;
-
- return 0;
+ ret = -EFAULT;
+ break;
}
default:
- printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
- cmd);
+ ret = -ENOTTY;
}
- return -EINVAL;
+ return ret;
}
static const struct file_operations hidraw_ops = {
@@ -270,7 +274,7 @@ static const struct file_operations hidraw_ops = {
.poll = hidraw_poll,
.open = hidraw_open,
.release = hidraw_release,
- .ioctl = hidraw_ioctl,
+ .unlocked_ioctl = hidraw_ioctl,
};
void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
@@ -322,8 +326,9 @@ int hidraw_connect(struct hid_device *hid)
goto out;
}
- dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
- "%s%d", "hidraw", minor);
+ dev->dev = device_create_drvdata(hidraw_class, NULL,
+ MKDEV(hidraw_major, minor), NULL,
+ "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
spin_lock(&minors_lock);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 01427c51c7c..27fe4d8912c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -122,7 +122,7 @@ static void hid_reset(struct work_struct *work)
dev_dbg(&usbhid->intf->dev, "resetting device\n");
rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
if (rc_lock >= 0) {
- rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf);
+ rc = usb_reset_device(hid_to_usb_dev(hid));
if (rc_lock)
usb_unlock_device(hid_to_usb_dev(hid));
}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1df832a8fcb..61e78a4369b 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -69,12 +69,18 @@
#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220
#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221
#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a
#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
@@ -241,6 +247,8 @@
#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_LX3 0xc044
+#define USB_DEVICE_ID_LOGITECH_V150 0xc047
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
@@ -314,6 +322,7 @@
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
+#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
@@ -443,7 +452,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
@@ -593,6 +603,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
@@ -642,6 +654,12 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
@@ -1128,7 +1146,7 @@ static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
&& rdesc[557] == 0x19
&& rdesc[559] == 0x29) {
printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
- rdesc[284] = rdesc[304] = rdesc[558] = 0x35;
+ rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
rdesc[352] = 0x36;
rdesc[286] = rdesc[355] = 0x46;
rdesc[306] = rdesc[559] = 0x45;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 95cc192bc7a..842e9edb888 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -406,6 +406,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
if (!uref_multi)
return -ENOMEM;
+ lock_kernel();
uref = &uref_multi->uref;
if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
if (copy_from_user(uref_multi, user_arg,
@@ -501,12 +502,15 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
}
goodreturn:
+ unlock_kernel();
kfree(uref_multi);
return 0;
fault:
+ unlock_kernel();
kfree(uref_multi);
return -EFAULT;
inval:
+ unlock_kernel();
kfree(uref_multi);
return -EINVAL;
}
@@ -540,7 +544,7 @@ static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd,
return len;
}
-static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct hiddev_list *list = file->private_data;
struct hiddev *hiddev = list->hiddev;
@@ -555,7 +559,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
int i;
+
+ /* Called without BKL by compat methods so no BKL taken */
+ /* FIXME: Who or what stop this racing with a disconnect ?? */
if (!hiddev->exist)
return -EIO;
@@ -756,8 +763,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
#ifdef CONFIG_COMPAT
static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg));
+ return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
}
#endif
@@ -768,7 +774,7 @@ static const struct file_operations hiddev_fops = {
.poll = hiddev_poll,
.open = hiddev_open,
.release = hiddev_release,
- .ioctl = hiddev_ioctl,
+ .unlocked_ioctl = hiddev_ioctl,
.fasync = hiddev_fasync,
#ifdef CONFIG_COMPAT
.compat_ioctl = hiddev_compat_ioctl,
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 3cd46d2e53c..0caaafe0184 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -43,7 +43,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
-static unsigned char usb_kbd_keycode[256] = {
+static const unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
@@ -233,14 +233,6 @@ static int usb_kbd_probe(struct usb_interface *iface,
if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
-#ifdef CONFIG_USB_HID
- if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct))
- & HID_QUIRK_IGNORE) {
- return -ENODEV;
- }
-#endif
-
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 703e9d0e871..35689ef172c 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -129,14 +129,6 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
-#ifdef CONFIG_USB_HID
- if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct))
- & (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
- return -ENODEV;
- }
-#endif
-
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 50f22690d61..a4d92d246d5 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -581,6 +581,8 @@ static int __init hdaps_init(void)
/* initialize the input class */
idev = hdaps_idev->input;
idev->name = "hdaps";
+ idev->phys = "isa1600/input0";
+ idev->id.bustype = BUS_ISA;
idev->dev.parent = &pdev->dev;
idev->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(idev, ABS_X,
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 3db28450a3b..7321a88a511 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,7 +55,8 @@ again:
return ERR_PTR(err);
id = id & MAX_ID_MASK;
- hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id);
+ hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
+ HWMON_ID_FORMAT, id);
if (IS_ERR(hwdev)) {
spin_lock(&idr_lock);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7608df83d6d..7bf38c41808 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -722,7 +722,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
INIT_LIST_HEAD(&driver->clients);
/* Walk the adapters that are already present */
- class_for_each_device(&i2c_adapter_class, driver, __attach_adapter);
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __attach_adapter);
mutex_unlock(&core_lock);
return 0;
@@ -782,7 +783,8 @@ void i2c_del_driver(struct i2c_driver *driver)
{
mutex_lock(&core_lock);
- class_for_each_device(&i2c_adapter_class, driver, __detach_adapter);
+ class_for_each_device(&i2c_adapter_class, NULL, driver,
+ __detach_adapter);
driver_unregister(&driver->driver);
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 86727fa8858..9d55c6383b2 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */
- i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
- MKDEV(I2C_MAJOR, adap->nr),
- "i2c-%d", adap->nr);
+ i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
+ MKDEV(I2C_MAJOR, adap->nr),
+ NULL, "i2c-%d", adap->nr);
if (IS_ERR(i2c_dev->dev)) {
res = PTR_ERR(i2c_dev->dev);
goto error;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 15b09b89588..04d9c4d459d 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -510,6 +510,7 @@ config BLK_DEV_TRIFLEX
config BLK_DEV_CY82C693
tristate "CY82C693 chipset support"
+ depends on ALPHA
select IDE_TIMINGS
select BLK_DEV_IDEDMA_PCI
help
@@ -548,6 +549,7 @@ config BLK_DEV_CS5535
config BLK_DEV_HPT34X
tristate "HPT34X chipset support"
+ depends on BROKEN
select BLK_DEV_IDEDMA_PCI
help
This driver adds up to 4 more EIDE devices sharing a single
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 52f58c88578..f575e8341ae 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -72,7 +72,7 @@ struct icside_state {
void __iomem *ioc_base;
unsigned int sel;
unsigned int type;
- ide_hwif_t *hwif[2];
+ struct ide_host *host;
};
#define ICS_TYPE_A3IN 0
@@ -375,12 +375,14 @@ static int icside_dma_test_irq(ide_drive_t *drive)
static void icside_dma_timeout(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
+
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
if (icside_dma_test_irq(drive))
return;
- ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
+ ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
icside_dma_end(drive);
}
@@ -440,10 +442,10 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __init
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif;
void __iomem *base;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int ret;
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
@@ -463,22 +465,23 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
- hwif = ide_find_port();
- if (!hwif)
+ host = ide_host_alloc(NULL, hws);
+ if (host == NULL)
return -ENODEV;
- ide_init_port_hw(hwif, &hw);
- default_hwif_mmiops(hwif);
-
- state->hwif[0] = hwif;
+ state->host = host;
ecard_set_drvdata(ec, state);
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+ ecard_set_drvdata(ec, NULL);
+ return ret;
}
static const struct ide_port_info icside_v6_port_info __initdata = {
@@ -493,13 +496,12 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
static int __init
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
- ide_hwif_t *hwif, *mate;
void __iomem *ioc_base, *easi_base;
+ struct ide_host *host;
unsigned int sel = 0;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
struct ide_port_info d = icside_v6_port_info;
- hw_regs_t hw[2];
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
@@ -538,28 +540,11 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
- /*
- * Find and register the interfaces.
- */
- hwif = ide_find_port();
- if (hwif == NULL)
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL)
return -ENODEV;
- ide_init_port_hw(hwif, &hw[0]);
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- mate = ide_find_port();
- if (mate) {
- ide_init_port_hw(mate, &hw[1]);
- default_hwif_mmiops(mate);
-
- idx[1] = mate->index;
- }
-
- state->hwif[0] = hwif;
- state->hwif[1] = mate;
+ state->host = host;
ecard_set_drvdata(ec, state);
@@ -569,11 +554,17 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
d.dma_ops = NULL;
}
- ide_device_add(idx, &d);
+ ret = ide_host_register(host, NULL, hws);
+ if (ret)
+ goto err_free;
return 0;
-
- out:
+err_free:
+ ide_host_free(host);
+ if (d.dma_ops)
+ free_dma(ec->dma);
+ ecard_set_drvdata(ec, NULL);
+out:
return ret;
}
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 2f311da4c96..176532ffae0 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -28,10 +28,8 @@
static int __init ide_arm_init(void)
{
- ide_hwif_t *hwif;
- hw_regs_t hw;
unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(base, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -51,15 +49,7 @@ static int __init ide_arm_init(void)
hw.irq = IDE_ARM_IRQ;
hw.chipset = ide_generic;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
- }
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(ide_arm_init);
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
index c79b85b6e4a..65bb4b8fd57 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/arm/palm_bk3710.c
@@ -316,15 +316,14 @@ static u8 __devinit palm_bk3710_cable_detect(ide_hwif_t *hwif)
static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- unsigned long base =
- hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-
printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name);
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
+
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -348,11 +347,10 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
{
struct clk *clk;
struct resource *mem, *irq;
- ide_hwif_t *hwif;
+ struct ide_host *host;
unsigned long base, rate;
- int i;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
clk = clk_get(NULL, "IDECLK");
if (IS_ERR(clk))
@@ -394,24 +392,14 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
hw.irq = irq->start;
hw.chipset = ide_palm3710;
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+ if (rc)
goto out;
- i = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- default_hwif_mmiops(hwif);
-
- idx[0] = i;
-
- ide_device_add(idx, &palm_bk3710_port_info);
-
return 0;
out:
printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
- return -ENODEV;
+ return rc;
}
/* work with hotplug and coldplug */
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 43057e0303c..2bdd8b734af 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -32,11 +32,10 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __devinit
rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
{
- ide_hwif_t *hwif;
void __iomem *base;
+ struct ide_host *host;
int ret;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
ret = ecard_request_resources(ec);
if (ret)
@@ -53,20 +52,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
hw.chipset = ide_generic;
hw.dev = &ec->dev;
- hwif = ide_find_port();
- if (hwif == NULL) {
- ret = -ENOENT;
+ ret = ide_host_add(&rapide_port_info, hws, &host);
+ if (ret)
goto release;
- }
-
- ide_init_port_hw(hwif, &hw);
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, &rapide_port_info);
- ecard_set_drvdata(ec, hwif);
+ ecard_set_drvdata(ec, host);
goto out;
release:
@@ -77,11 +67,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit rapide_remove(struct expansion_card *ec)
{
- ide_hwif_t *hwif = ecard_get_drvdata(ec);
+ struct ide_host *host = ecard_get_drvdata(ec);
ecard_set_drvdata(ec, NULL);
- ide_unregister(hwif);
+ ide_host_remove(host);
ecard_release_resources(ec);
}
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 20fad6d542c..bde7a585f19 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -100,6 +100,8 @@ static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -153,6 +155,21 @@ static void h8300_output_data(ide_drive_t *drive, struct request *rq,
mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
+static const struct ide_tp_ops h8300_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = h8300_tf_load,
+ .tf_read = h8300_tf_read,
+
+ .input_data = h8300_input_data,
+ .output_data = h8300_output_data,
+};
+
#define H8300_IDE_GAP (2)
static inline void hw_setup(hw_regs_t *hw)
@@ -167,27 +184,14 @@ static inline void hw_setup(hw_regs_t *hw)
hw->chipset = ide_generic;
}
-static inline void hwif_setup(ide_hwif_t *hwif)
-{
- default_hwif_iops(hwif);
-
- hwif->tf_load = h8300_tf_load;
- hwif->tf_read = h8300_tf_read;
-
- hwif->input_data = h8300_input_data;
- hwif->output_data = h8300_output_data;
-}
-
static const struct ide_port_info h8300_port_info = {
+ .tp_ops = &h8300_tp_ops,
.host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
};
static int __init h8300_ide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int index;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
@@ -200,19 +204,7 @@ static int __init h8300_ide_init(void)
hw_setup(&hw);
- hwif = ide_find_port_slot(&h8300_port_info);
- if (hwif == NULL)
- return -ENOENT;
-
- index = hwif->index;
- ide_init_port_hw(hwif, &hw);
- hwif_setup(hwif);
-
- idx[0] = index;
-
- ide_device_add(idx, &h8300_port_info);
-
- return 0;
+ return ide_host_add(&h8300_port_info, hws, NULL);
out_busy:
printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2802031de67..adf04f99cde 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -22,6 +22,8 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc;
unsigned int temp;
u16 bcount;
@@ -30,12 +32,12 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
debug_log("Enter %s - interrupt handler\n", __func__);
if (pc->flags & PC_FLAG_TIMEDOUT) {
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
/* Clear the interrupt */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) ||
@@ -63,8 +65,9 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_enable_in_hardirq();
if (drive->media == ide_tape && !scsi &&
- (stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+ (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE)
stat &= ~ERR_STAT;
+
if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
/* Error detected */
debug_log("%s: I/O error\n", drive->name);
@@ -75,16 +78,17 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
goto cmd_finished;
}
- if (pc->c[0] == REQUEST_SENSE) {
+ if (rq->cmd[0] == REQUEST_SENSE) {
printk(KERN_ERR "%s: I/O error in request sense"
" command\n", drive->name);
return ide_do_reset(drive);
}
- debug_log("[cmd %x]: check condition\n", pc->c[0]);
+ debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
/* Retry operation */
retry_pc(drive);
+
/* queued, but not started */
return ide_stopped;
}
@@ -95,8 +99,10 @@ cmd_finished:
dsc_handle(drive);
return ide_stopped;
}
+
/* Command finished - Call the callback function */
- pc->callback(drive);
+ drive->pc_callback(drive);
+
return ide_stopped;
}
@@ -107,16 +113,15 @@ cmd_finished:
ide_dma_off(drive);
return ide_do_reset(drive);
}
- /* Get the number of bytes to transfer on this interrupt. */
- bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
- hwif->INB(hwif->io_ports.lbam_addr);
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ /* Get the number of bytes to transfer on this interrupt. */
+ ide_read_bcount_and_ireason(drive, &bcount, &ireason);
if (ireason & CD) {
printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
return ide_do_reset(drive);
}
+
if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
/* Hopefully, we will never get here */
printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
@@ -125,6 +130,7 @@ cmd_finished:
(ireason & IO) ? "Read" : "Write");
return ide_do_reset(drive);
}
+
if (!(pc->flags & PC_FLAG_WRITING)) {
/* Reading - Check that we have enough space */
temp = pc->xferred + bcount;
@@ -142,7 +148,7 @@ cmd_finished:
if (pc->sg)
io_buffers(drive, pc, temp, 0);
else
- hwif->input_data(drive, NULL,
+ tp_ops->input_data(drive, NULL,
pc->cur_pos, temp);
printk(KERN_ERR "%s: transferred %d of "
"%d bytes\n",
@@ -159,9 +165,9 @@ cmd_finished:
debug_log("The device wants to send us more data than "
"expected - allowing transfer\n");
}
- xferfunc = hwif->input_data;
+ xferfunc = tp_ops->input_data;
} else
- xferfunc = hwif->output_data;
+ xferfunc = tp_ops->output_data;
if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
(drive->media == ide_tape && !scsi && pc->bh) ||
@@ -175,7 +181,7 @@ cmd_finished:
pc->cur_pos += bcount;
debug_log("[cmd %x] transferred %d bytes on that intr.\n",
- pc->c[0], bcount);
+ rq->cmd[0], bcount);
/* And set the interrupt handler again */
ide_set_handler(drive, handler, timeout, expiry);
@@ -183,16 +189,27 @@ cmd_finished:
}
EXPORT_SYMBOL_GPL(ide_pc_intr);
+static u8 ide_read_ireason(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.nsect & 3;
+}
+
static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
{
- ide_hwif_t *hwif = drive->hwif;
int retries = 100;
while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, retrying\n", drive->name);
udelay(100);
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ ireason = ide_read_ireason(drive);
if (retries == 0) {
printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
"a packet command, ignoring\n",
@@ -210,6 +227,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
ide_expiry_t *expiry)
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
ide_startstop_t startstop;
u8 ireason;
@@ -219,7 +237,7 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
return startstop;
}
- ireason = hwif->INB(hwif->io_ports.nsect_addr);
+ ireason = ide_read_ireason(drive);
if (drive->media == ide_tape && !drive->scsi)
ireason = ide_wait_ireason(drive, ireason);
@@ -239,8 +257,8 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
}
/* Send the actual packet */
- if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
- hwif->output_data(drive, NULL, pc->c, 12);
+ if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
return ide_started;
}
@@ -284,7 +302,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
bcount, dma);
/* Issue the packet command */
- if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
ide_execute_command(drive, WIN_PACKETCMD, handler,
timeout, NULL);
return ide_started;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6e29dd53209..4e73aeee405 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -85,10 +85,8 @@ static void ide_cd_put(struct cdrom_info *cd)
/* Mark that we've seen a media change and invalidate our internal buffers. */
static void cdrom_saw_media_change(ide_drive_t *drive)
{
- struct cdrom_info *cd = drive->driver_data;
-
- cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -280,11 +278,12 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
*/
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
int stat, err, sense_key;
/* check for errors */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat_ret)
*stat_ret = stat;
@@ -528,7 +527,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
xferlen, info->dma);
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/* waiting for CDB interrupt, not DMA yet. */
if (info->dma)
drive->waiting_for_dma = 0;
@@ -560,7 +559,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
/*
* Here we should have been called after receiving an interrupt
* from the device. DRQ should how be set.
@@ -589,7 +588,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
cmd_len = ATAPI_MIN_CDB_BYTES;
/* send the command to the device */
- hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */
if (info->dma)
@@ -606,6 +605,8 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
int len, int ireason, int rw)
{
+ ide_hwif_t *hwif = drive->hwif;
+
/*
* ireason == 0: the drive wants to receive data from us
* ireason == 2: the drive is expecting to transfer data to us
@@ -624,7 +625,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
* Some drives (ASUS) seem to tell us that status info is
* available. Just get it and ignore.
*/
- (void)ide_read_status(drive);
+ (void)hwif->tp_ops->read_status(hwif);
return 0;
} else {
/* drive wants a command packet, or invalid ireason... */
@@ -645,20 +646,18 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
*/
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
- struct cdrom_info *cd = drive->driver_data;
-
if ((len % SECTOR_SIZE) == 0)
return 0;
printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
drive->name, __func__, len);
- if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+ if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
printk(KERN_ERR " This drive is not supported by "
"this version of the driver\n");
else {
printk(KERN_ERR " Trying to limit transfer sizes\n");
- cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
+ drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
}
return 1;
@@ -735,7 +734,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- info->cd_flags |= IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags |= IDE_AFLAG_SEEKING;
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
if (--retry == 0)
@@ -892,10 +891,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
struct request *rq = HWGROUP(drive)->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
- int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+ int dma_error = 0, dma, stat, thislen, uptodate = 0;
int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
unsigned int timeout;
- u8 lowcyl, highcyl;
+ u16 len;
+ u8 ireason;
/* check for errors */
dma = info->dma;
@@ -923,12 +923,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
goto end_request;
}
- /* ok we fall to pio :/ */
- ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
- lowcyl = hwif->INB(hwif->io_ports.lbam_addr);
- highcyl = hwif->INB(hwif->io_ports.lbah_addr);
-
- len = lowcyl + (256 * highcyl);
+ ide_read_bcount_and_ireason(drive, &len, &ireason);
thislen = blk_fs_request(rq) ? len : rq->data_len;
if (thislen > len)
@@ -991,10 +986,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (ireason == 0) {
write = 1;
- xferfunc = hwif->output_data;
+ xferfunc = hwif->tp_ops->output_data;
} else {
write = 0;
- xferfunc = hwif->input_data;
+ xferfunc = hwif->tp_ops->input_data;
}
/* transfer data */
@@ -1198,9 +1193,10 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
int xferlen;
if (blk_fs_request(rq)) {
- if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+ if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long elapsed = jiffies - info->start_seek;
- int stat = ide_read_status(drive);
+ int stat = hwif->tp_ops->read_status(hwif);
if ((stat & SEEK_STAT) != SEEK_STAT) {
if (elapsed < IDECD_SEEK_TIMEOUT) {
@@ -1211,7 +1207,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
printk(KERN_ERR "%s: DSC timeout\n",
drive->name);
}
- info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
}
if (rq_data_dir(rq) == READ &&
IDE_LARGE_SEEK(info->last_block, block,
@@ -1288,7 +1284,7 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
*/
cmd[7] = cdi->sanyo_slot % 3;
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, REQ_QUIET);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
}
static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -1296,8 +1292,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
struct request_sense *sense)
{
struct {
- __u32 lba;
- __u32 blocklen;
+ __be32 lba;
+ __be32 blocklen;
} capbuf;
int stat;
@@ -1369,7 +1365,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
*/
(void) cdrom_check_status(drive, sense);
- if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
return 0;
/* try to get the total cdrom capacity and sector size */
@@ -1391,7 +1387,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
@@ -1432,7 +1428,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
return stat;
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
} else {
@@ -1446,14 +1442,14 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
}
for (i = 0; i <= ntracks; i++) {
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
- if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
toc->ent[i].track = BCD2BIN(toc->ent[i].track);
msf_from_bcd(&toc->ent[i].addr.msf);
}
@@ -1476,7 +1472,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
}
- if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
/* re-read multisession information using MSF format */
stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
sizeof(ms_tmp), sense);
@@ -1500,7 +1496,7 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
}
/* Remember that we've read this stuff. */
- info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
return 0;
}
@@ -1512,7 +1508,7 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
struct packet_command cgc;
int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
@@ -1530,15 +1526,12 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
struct cdrom_info *cd = drive->driver_data;
u16 curspeed, maxspeed;
- curspeed = *(u16 *)&buf[8 + 14];
- maxspeed = *(u16 *)&buf[8 + 8];
-
- if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
- curspeed = le16_to_cpu(curspeed);
- maxspeed = le16_to_cpu(maxspeed);
+ if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
+ curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
+ maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
} else {
- curspeed = be16_to_cpu(curspeed);
- maxspeed = be16_to_cpu(maxspeed);
+ curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
+ maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
}
cd->current_speed = (curspeed + (176/2)) / 176;
@@ -1579,7 +1572,7 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
devinfo->handle = drive;
strcpy(devinfo->name, drive->name);
- if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
devinfo->mask |= CDC_SELECT_SPEED;
devinfo->disk = info->disk;
@@ -1605,8 +1598,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return nslots;
}
- if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
cdi->mask &= ~CDC_PLAY_AUDIO;
return nslots;
}
@@ -1624,9 +1617,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
return 0;
if ((buf[8 + 6] & 0x01) == 0)
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
if (buf[8 + 6] & 0x08)
- cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+ drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
if (buf[8 + 3] & 0x01)
cdi->mask &= ~CDC_CD_R;
if (buf[8 + 3] & 0x02)
@@ -1637,7 +1630,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
if (buf[8 + 3] & 0x10)
cdi->mask &= ~CDC_DVD_R;
- if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+ if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
cdi->mask &= ~CDC_PLAY_AUDIO;
mechtype = buf[8 + 6] >> 5;
@@ -1679,7 +1672,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
else
printk(KERN_CONT " drive");
- printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+ printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
return nslots;
}
@@ -1802,43 +1795,43 @@ static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
static const struct cd_list_entry ide_cd_quirks_list[] = {
/* Limit transfer size per interrupt. */
- { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
- { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_AFLAG_LIMIT_NFRAMES },
+ { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_AFLAG_LIMIT_NFRAMES },
/* SCR-3231 doesn't support the SET_CD_SPEED command. */
- { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
+ { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_NO_SPEED_SELECT },
/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
- { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
- IDE_CD_FLAG_PRE_ATAPI12, },
+ { "NEC CD-ROM DRIVE:260", "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
+ IDE_AFLAG_PRE_ATAPI12, },
/* Vertos 300, some versions of this drive like to talk BCD. */
- { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
+ { "V003S0DS", NULL, IDE_AFLAG_VERTOS_300_SSD, },
/* Vertos 600 ESD. */
- { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
+ { "V006E0DS", NULL, IDE_AFLAG_VERTOS_600_ESD, },
/*
* Sanyo 3 CD changer uses a non-standard command for CD changing
* (by default standard ATAPI support for CD changers is used).
*/
- { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
- { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3 G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR-C3G", NULL, IDE_AFLAG_SANYO_3CD },
+ { "CD-ROM CDR_C36", NULL, IDE_AFLAG_SANYO_3CD },
/* Stingray 8X CD-ROM. */
- { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+ { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_PRE_ATAPI12 },
/*
* ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
* mode sense page capabilities size, but older drives break.
*/
- { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
- { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
+ { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
+ { "WPI CDS-32X", NULL, IDE_AFLAG_FULL_CAPS_PAGE },
/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
- { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
+ { "", "241N", IDE_AFLAG_LE_SPEED_FIELDS },
/*
* Some drives used by Apple don't advertise audio play
* but they do support reading TOC & audio datas.
*/
- { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
- { "Optiarc DVD RW AD-5200A", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8187", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8186", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8176", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "MATSHITADVD-ROM SR-8174", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
+ { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK },
{ NULL, NULL, 0 }
};
@@ -1873,20 +1866,20 @@ static int ide_cdrom_setup(ide_drive_t *drive)
drive->special.all = 0;
- cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+ drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
ide_cd_flags(id);
if ((id->config & 0x0060) == 0x20)
- cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
- if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+ if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
- IDE_CD_FLAG_TOCADDR_AS_BCD);
- else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+ drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
+ IDE_AFLAG_TOCADDR_AS_BCD);
+ else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
- cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
- else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+ drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
+ else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
/* 3 => use CD in slot 0 */
cdi->sanyo_slot = 3;
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index fe0ea36e412..61a4599b77d 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -27,42 +27,6 @@
#define ATAPI_CAPABILITIES_PAGE_SIZE (8 + 20)
#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE 4
-enum {
- /* Device sends an interrupt when ready for a packet command. */
- IDE_CD_FLAG_DRQ_INTERRUPT = (1 << 0),
- /* Drive cannot lock the door. */
- IDE_CD_FLAG_NO_DOORLOCK = (1 << 1),
- /* Drive cannot eject the disc. */
- IDE_CD_FLAG_NO_EJECT = (1 << 2),
- /* Drive is a pre ATAPI 1.2 drive. */
- IDE_CD_FLAG_PRE_ATAPI12 = (1 << 3),
- /* TOC addresses are in BCD. */
- IDE_CD_FLAG_TOCADDR_AS_BCD = (1 << 4),
- /* TOC track numbers are in BCD. */
- IDE_CD_FLAG_TOCTRACKS_AS_BCD = (1 << 5),
- /*
- * Drive does not provide data in multiples of SECTOR_SIZE
- * when more than one interrupt is needed.
- */
- IDE_CD_FLAG_LIMIT_NFRAMES = (1 << 6),
- /* Seeking in progress. */
- IDE_CD_FLAG_SEEKING = (1 << 7),
- /* Driver has noticed a media change. */
- IDE_CD_FLAG_MEDIA_CHANGED = (1 << 8),
- /* Saved TOC information is current. */
- IDE_CD_FLAG_TOC_VALID = (1 << 9),
- /* We think that the drive door is locked. */
- IDE_CD_FLAG_DOOR_LOCKED = (1 << 10),
- /* SET_CD_SPEED command is unsupported. */
- IDE_CD_FLAG_NO_SPEED_SELECT = (1 << 11),
- IDE_CD_FLAG_VERTOS_300_SSD = (1 << 12),
- IDE_CD_FLAG_VERTOS_600_ESD = (1 << 13),
- IDE_CD_FLAG_SANYO_3CD = (1 << 14),
- IDE_CD_FLAG_FULL_CAPS_PAGE = (1 << 15),
- IDE_CD_FLAG_PLAY_AUDIO_OK = (1 << 16),
- IDE_CD_FLAG_LE_SPEED_FIELDS = (1 << 17),
-};
-
/* Structure of a MSF cdrom address. */
struct atapi_msf {
byte reserved;
@@ -128,8 +92,6 @@ struct cdrom_info {
unsigned long last_block;
unsigned long start_seek;
- unsigned int cd_flags;
-
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 24d002addf7..74231b41f61 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -27,10 +27,9 @@ int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
void ide_cdrom_release_real(struct cdrom_device_info *cdi)
{
ide_drive_t *drive = cdi->handle;
- struct cdrom_info *cd = drive->driver_data;
if (!cdi->use_count)
- cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+ drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
}
/*
@@ -83,13 +82,12 @@ int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
int slot_nr)
{
ide_drive_t *drive = cdi->handle;
- struct cdrom_info *cd = drive->driver_data;
int retval;
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status(drive, NULL);
- retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
- cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
+ retval = (drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED) ? 1 : 0;
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return retval;
} else {
return -EINVAL;
@@ -107,11 +105,11 @@ int cdrom_eject(ide_drive_t *drive, int ejectflag,
char loej = 0x02;
unsigned char cmd[BLK_MAX_CDB];
- if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+ if ((drive->atapi_flags & IDE_AFLAG_NO_EJECT) && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
/* reload fails on some drives, if the tray is locked */
- if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
+ if ((drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED) && ejectflag)
return 0;
/* only tell drive to close tray if open, if it can do that */
@@ -123,7 +121,7 @@ int cdrom_eject(ide_drive_t *drive, int ejectflag,
cmd[0] = GPCMD_START_STOP_UNIT;
cmd[4] = loej | (ejectflag != 0);
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, 0);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, 0);
}
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
@@ -131,7 +129,6 @@ static
int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
struct request_sense *sense)
{
- struct cdrom_info *cd = drive->driver_data;
struct request_sense my_sense;
int stat;
@@ -139,7 +136,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
sense = &my_sense;
/* If the drive cannot lock the door, just pretend. */
- if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
+ if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK) {
stat = 0;
} else {
unsigned char cmd[BLK_MAX_CDB];
@@ -149,7 +146,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
cmd[4] = lockflag ? 1 : 0;
- stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0,
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL,
sense, 0, 0);
}
@@ -160,7 +157,7 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
(sense->asc == 0x24 || sense->asc == 0x20)) {
printk(KERN_ERR "%s: door locking not supported\n",
drive->name);
- cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+ drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
stat = 0;
}
@@ -170,9 +167,9 @@ int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
if (stat == 0) {
if (lockflag)
- cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags |= IDE_AFLAG_DOOR_LOCKED;
else
- cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+ drive->atapi_flags &= ~IDE_AFLAG_DOOR_LOCKED;
}
return stat;
@@ -231,7 +228,7 @@ int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
cmd[5] = speed & 0xff;
}
- stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+ stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
if (!ide_cdrom_get_capabilities(drive, buf)) {
ide_cdrom_update_speed(drive, buf);
@@ -250,7 +247,7 @@ int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
struct request_sense sense;
int ret;
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0 || !info->toc) {
ret = ide_cd_read_toc(drive, &sense);
if (ret)
return ret;
@@ -308,7 +305,7 @@ int ide_cdrom_reset(struct cdrom_device_info *cdi)
* A reset will unlock the door. If it was previously locked,
* lock it again.
*/
- if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+ if (drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED)
(void)ide_cd_lockdoor(drive, 1, &sense);
return ret;
@@ -324,7 +321,7 @@ static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
/*
* don't serve cached data, if the toc isn't valid
*/
- if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+ if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0)
return -EINVAL;
/* Check validity of requested track number. */
@@ -374,7 +371,7 @@ static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
lba_to_msf(lba_start, &cmd[3], &cmd[4], &cmd[5]);
lba_to_msf(lba_end - 1, &cmd[6], &cmd[7], &cmd[8]);
- return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+ return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
}
static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 3a2e80237c1..df5fe575687 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -158,7 +158,7 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
if (dma)
- index = drive->vdma ? 4 : 8;
+ index = 8;
else
index = drive->mult_count ? 0 : 4;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 7ee44f86bc5..be99d463dcc 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -100,10 +100,11 @@ static const struct drive_list_entry drive_blacklist [] = {
ide_startstop_t ide_dma_intr (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
u8 stat = 0, dma_stat = 0;
- dma_stat = drive->hwif->dma_ops->dma_end(drive);
- stat = ide_read_status(drive);
+ dma_stat = hwif->dma_ops->dma_end(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) {
@@ -334,7 +335,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
static int dma_timer_expiry (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
drive->name, dma_stat);
@@ -369,14 +370,18 @@ void ide_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = HWIF(drive);
u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- hwif->OUTB(dma_stat, hwif->dma_status);
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(dma_stat,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
}
EXPORT_SYMBOL_GPL(ide_dma_host_set);
@@ -449,6 +454,7 @@ int ide_dma_setup(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
unsigned int reading;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat;
if (rq_data_dir(rq))
@@ -470,13 +476,21 @@ int ide_dma_setup(ide_drive_t *drive)
outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
/* specify r/w */
- hwif->OUTB(reading, hwif->dma_command);
+ if (mmio)
+ writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ else
+ outb(reading, hwif->dma_base + ATA_DMA_CMD);
- /* read dma_status for INTR & ERROR flags */
- dma_stat = hwif->INB(hwif->dma_status);
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
/* clear INTR & ERROR flags */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ if (mmio)
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
drive->waiting_for_dma = 1;
return 0;
}
@@ -492,16 +506,24 @@ EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
void ide_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- u8 dma_cmd = hwif->INB(hwif->dma_command);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 dma_cmd;
/* Note that this is done *after* the cmd has
* been issued to the drive, as per the BM-IDE spec.
* The Promise Ultra33 doesn't work correctly when
* we do this part before issuing the drive cmd.
*/
- /* start DMA */
- hwif->OUTB(dma_cmd|1, hwif->dma_command);
+ if (hwif->host_flags & IDE_HFLAG_MMIO) {
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* start DMA */
+ writeb(dma_cmd | 1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
hwif->dma = 1;
wmb();
}
@@ -511,18 +533,33 @@ EXPORT_SYMBOL_GPL(ide_dma_start);
/* returns 1 on error, 0 otherwise */
int __ide_dma_end (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- /* get dma_command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
- /* stop DMA */
- hwif->OUTB(dma_cmd&~1, hwif->dma_command);
+
+ if (mmio) {
+ /* get DMA command mode */
+ dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ /* stop DMA */
+ writeb(dma_cmd & ~1,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+ } else {
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+ }
+
/* get DMA status */
- dma_stat = hwif->INB(hwif->dma_status);
- /* clear the INTR & ERROR bits */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+ if (mmio)
+ /* clear the INTR & ERROR bits */
+ writeb(dma_stat | 6,
+ (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -537,7 +574,7 @@ EXPORT_SYMBOL(__ide_dma_end);
int ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
/* return 1 if INTR asserted */
if ((dma_stat & 4) == 4)
@@ -719,9 +756,8 @@ static int ide_tune_dma(ide_drive_t *drive)
static int ide_dma_check(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0;
- if (!vdma && ide_tune_dma(drive))
+ if (ide_tune_dma(drive))
return 0;
/* TODO: always do PIO fallback */
@@ -730,7 +766,7 @@ static int ide_dma_check(ide_drive_t *drive)
ide_set_max_pio(drive);
- return vdma ? 0 : -1;
+ return -1;
}
int ide_id_dma_bug(ide_drive_t *drive)
@@ -842,7 +878,7 @@ int ide_allocate_dma_engine(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
-static const struct ide_dma_ops sff_dma_ops = {
+const struct ide_dma_ops sff_dma_ops = {
.dma_host_set = ide_dma_host_set,
.dma_setup = ide_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd,
@@ -852,18 +888,5 @@ static const struct ide_dma_ops sff_dma_ops = {
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
};
-
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
-{
- hwif->dma_base = base;
-
- if (!hwif->dma_command)
- hwif->dma_command = hwif->dma_base + 0;
- if (!hwif->dma_status)
- hwif->dma_status = hwif->dma_base + 2;
-
- hwif->dma_ops = &sff_dma_ops;
-}
-
-EXPORT_SYMBOL_GPL(ide_setup_dma);
+EXPORT_SYMBOL_GPL(sff_dma_ops);
#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 011d72011cc..3d8e6dd0f41 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -125,26 +125,10 @@ typedef struct ide_floppy_obj {
int wp;
/* Supports format progress report */
int srfp;
- /* Status/Action flags */
- unsigned long flags;
} idefloppy_floppy_t;
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
-/* Floppy flag bits values. */
-enum {
- /* DRQ interrupt device */
- IDEFLOPPY_FLAG_DRQ_INTERRUPT = (1 << 0),
- /* Media may have changed */
- IDEFLOPPY_FLAG_MEDIA_CHANGED = (1 << 1),
- /* Format in progress */
- IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS = (1 << 2),
- /* Avoid commands not supported in Clik drive */
- IDEFLOPPY_FLAG_CLIK_DRIVE = (1 << 3),
- /* Requires BH algorithm for packets */
- IDEFLOPPY_FLAG_ZIP_DRIVE = (1 << 4),
-};
-
/* Defines for the MODE SENSE command */
#define MODE_SENSE_CURRENT 0x00
#define MODE_SENSE_CHANGEABLE 0x01
@@ -247,9 +231,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
data = bvec_kmap_irq(bvec, &flags);
if (direction)
- hwif->output_data(drive, NULL, data, count);
+ hwif->tp_ops->output_data(drive, NULL, data, count);
else
- hwif->input_data(drive, NULL, data, count);
+ hwif->tp_ops->input_data(drive, NULL, data, count);
bvec_kunmap_irq(data, &flags);
bcount -= count;
@@ -291,6 +275,7 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_PREEMPT;
rq->rq_disk = floppy->disk;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
}
@@ -354,7 +339,6 @@ static void idefloppy_init_pc(struct ide_atapi_pc *pc)
memset(pc, 0, sizeof(*pc));
pc->buf = pc->pc_buf;
pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
- pc->callback = ide_floppy_callback;
}
static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -402,7 +386,7 @@ static int idefloppy_transfer_pc(ide_drive_t *drive)
idefloppy_floppy_t *floppy = drive->driver_data;
/* Send the actual packet */
- drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+ drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
/* Timeout for the packet command */
return IDEFLOPPY_WAIT_CMD;
@@ -429,7 +413,7 @@ static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
* 40 and 50msec work well. idefloppy_pc_intr will not be actually
* used until after the packet is moved in about 50 msec.
*/
- if (pc->flags & PC_FLAG_ZIP_DRIVE) {
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
timeout = floppy->ticks;
expiry = &idefloppy_transfer_pc;
} else {
@@ -474,7 +458,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->error = IDEFLOPPY_ERROR_GENERAL;
floppy->failed_pc = NULL;
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
@@ -574,6 +558,8 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
+ memcpy(rq->cmd, pc->c, 12);
+
pc->rq = rq;
pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
if (rq->cmd_flags & REQ_RW)
@@ -647,12 +633,6 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
return ide_stopped;
}
- if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT)
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
-
- if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE)
- pc->flags |= PC_FLAG_ZIP_DRIVE;
-
pc->rq = rq;
return idefloppy_issue_pc(drive, pc);
@@ -671,6 +651,7 @@ static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->buffer = (char *) pc;
rq->cmd_type = REQ_TYPE_SPECIAL;
+ memcpy(rq->cmd, pc->c, 12);
error = blk_execute_rq(drive->queue, floppy->disk, rq, 0);
blk_put_request(rq);
@@ -795,7 +776,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
switch (pc.buf[desc_start + 4] & 0x03) {
/* Clik! drive returns this instead of CAPACITY_CURRENT */
case CAPACITY_UNFORMATTED:
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
/*
* If it is not a clik drive, break out
* (maintains previous driver behaviour)
@@ -841,7 +822,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
}
/* Clik! disk does not support get_flexible_disk_page */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
(void) ide_floppy_get_flexible_disk_page(drive);
set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
@@ -949,11 +930,12 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
/* Else assume format_unit has finished, and we're at 0x10000 */
} else {
+ ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
u8 stat;
local_irq_save(flags);
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
local_irq_restore(flags);
progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
@@ -1039,9 +1021,10 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
*((u16 *) &gcw) = drive->id->config;
floppy->pc = floppy->pc_stack;
+ drive->pc_callback = ide_floppy_callback;
if (((gcw[0] & 0x60) >> 5) == 1)
- floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
/*
* We used to check revisions here. At this point however I'm giving up.
* Just assume they are all broken, its easier.
@@ -1052,7 +1035,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
* we'll leave the limitation below for the 2.2.x tree.
*/
if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
- floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
+ drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
/* This value will be visible in the /proc/ide/hdx/settings */
floppy->ticks = IDEFLOPPY_TICKS_DELAY;
blk_queue_max_sectors(drive->queue, 64);
@@ -1064,7 +1047,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
*/
if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
blk_queue_max_sectors(drive->queue, 64);
- floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
+ drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
}
(void) ide_floppy_get_capacity(drive);
@@ -1153,7 +1136,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
floppy->openers++;
if (floppy->openers == 1) {
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
/* Just in case */
idefloppy_init_pc(&pc);
@@ -1180,14 +1163,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
ret = -EROFS;
goto out_put_floppy;
}
- floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 1);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
check_disk_change(inode->i_bdev);
- } else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
+ } else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
ret = -EBUSY;
goto out_put_floppy;
}
@@ -1210,12 +1193,12 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
if (floppy->openers == 1) {
/* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
idefloppy_create_prevent_cmd(&pc, 0);
(void) idefloppy_queue_pc_tail(drive, &pc);
}
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
}
floppy->openers--;
@@ -1236,15 +1219,17 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
- struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd)
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ unsigned long arg, unsigned int cmd)
{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
if (floppy->openers > 1)
return -EBUSY;
/* The IOMEGA Clik! Drive doesn't support this command -
* no room for an eject mechanism */
- if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
int prevent = arg ? 1 : 0;
if (cmd == CDROMEJECT)
@@ -1265,16 +1250,17 @@ static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
int __user *arg)
{
- int blocks, length, flags, err = 0;
struct ide_atapi_pc pc;
+ ide_drive_t *drive = floppy->drive;
+ int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
/* Don't format if someone is using the disk */
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return -EBUSY;
}
- floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
/*
* Send ATAPI_FORMAT_UNIT to the drive.
@@ -1298,15 +1284,15 @@ static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
goto out;
}
- (void) idefloppy_get_sfrp_bit(floppy->drive);
+ (void) idefloppy_get_sfrp_bit(drive);
idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
- if (idefloppy_queue_pc_tail(floppy->drive, &pc))
+ if (idefloppy_queue_pc_tail(drive, &pc))
err = -EIO;
out:
if (err)
- floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
return err;
}
@@ -1325,7 +1311,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
case CDROMEJECT:
/* fall through */
case CDROM_LOCKDOOR:
- return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
+ return ide_floppy_lockdoor(drive, &pc, arg, cmd);
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
@@ -1366,8 +1352,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
drive->attach = 0;
return 0;
}
- ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
- floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
+ drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
return ret;
}
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 2d92214096a..31d98fec775 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -28,29 +28,21 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
static ssize_t store_add(struct class *cls, const char *buf, size_t n)
{
- ide_hwif_t *hwif;
unsigned int base, ctl;
- int irq;
- hw_regs_t hw;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+ int irq, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
return -EINVAL;
- hwif = ide_find_port();
- if (hwif == NULL)
- return -ENOENT;
-
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base, ctl);
hw.irq = irq;
hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, NULL);
+ rc = ide_host_add(NULL, hws, NULL);
+ if (rc)
+ return rc;
return n;
};
@@ -90,18 +82,18 @@ static int __init ide_generic_sysfs_init(void)
static int __init ide_generic_init(void)
{
- u8 idx[MAX_HWIFS];
- int i;
+ hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
+ struct ide_host *host;
+ unsigned long io_addr;
+ int i, rc;
printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
"parameter for probing all legacy ISA IDE ports\n");
for (i = 0; i < MAX_HWIFS; i++) {
- ide_hwif_t *hwif;
- unsigned long io_addr = ide_default_io_base(i);
- hw_regs_t hw;
+ io_addr = ide_default_io_base(i);
- idx[i] = 0xff;
+ hws[i] = NULL;
if ((probe_mask & (1 << i)) && io_addr) {
if (!request_region(io_addr, 8, DRV_NAME)) {
@@ -119,33 +111,42 @@ static int __init ide_generic_init(void)
continue;
}
- /*
- * Skip probing if the corresponding
- * slot is already occupied.
- */
- hwif = ide_find_port();
- if (hwif == NULL || hwif->index != i) {
- idx[i] = 0xff;
- continue;
- }
-
- memset(&hw, 0, sizeof(hw));
- ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
- hw.irq = ide_default_irq(io_addr);
- hw.chipset = ide_generic;
- ide_init_port_hw(hwif, &hw);
+ memset(&hw[i], 0, sizeof(hw[i]));
+ ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
+ hw[i].irq = ide_default_irq(io_addr);
+ hw[i].chipset = ide_generic;
- idx[i] = i;
+ hws[i] = &hw[i];
}
}
- ide_device_add_all(idx, NULL);
+ host = ide_host_alloc_all(NULL, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ rc = ide_host_register(host, NULL, hws);
+ if (rc)
+ goto err_free;
if (ide_generic_sysfs_init())
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
"class\n");
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (hws[i] == NULL)
+ continue;
+
+ io_addr = hws[i]->io_ports.data_addr;
+ release_region(io_addr + 0x206, 1);
+ release_region(io_addr, 8);
+ }
+ return rc;
}
module_init(ide_generic_init);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 661b75a89d4..a896a283f27 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -330,7 +330,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
tf->error = err;
tf->status = stat;
- drive->hwif->tf_read(drive, task);
+ drive->hwif->tp_ops->tf_read(drive, task);
if (task->tf_flags & IDE_TFLAG_DYN)
kfree(task);
@@ -381,8 +381,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
- hwif->INB(hwif->io_ports.command_addr) ==
- WIN_SPECIFY)
+ hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
@@ -408,7 +407,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
return ide_stopped;
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
rq->errors |= ERROR_RESET;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -435,10 +434,9 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
/* add decoding error stuff */
}
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
/* force an abort */
- hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq);
@@ -712,7 +710,8 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
- ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+ ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
+ ide_read_error(drive));
return ide_stopped;
}
@@ -747,16 +746,17 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* the bus may be broken enough to walk on our toes at this
* point.
*/
+ ide_hwif_t *hwif = drive->hwif;
int rc;
#ifdef DEBUG_PM
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
#endif
- rc = ide_wait_not_busy(HWIF(drive), 35000);
+ rc = ide_wait_not_busy(hwif, 35000);
if (rc)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
- rc = ide_wait_not_busy(HWIF(drive), 100000);
+ hwif->tp_ops->set_irq(hwif, 1);
+ rc = ide_wait_not_busy(hwif, 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
}
@@ -1042,7 +1042,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* quirk_list may not like intr setups/cleanups
*/
if (drive->quirk_list != 1)
- ide_set_irq(drive, 0);
+ hwif->tp_ops->set_irq(hwif, 0);
}
hwgroup->hwif = hwif;
hwgroup->drive = drive;
@@ -1142,7 +1142,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
(void)hwif->dma_ops->dma_end(drive);
ret = ide_error(drive, "dma timeout error",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
hwif->dma_ops->dma_timeout(drive);
@@ -1267,7 +1267,7 @@ void ide_timer_expiry (unsigned long data)
} else
startstop =
ide_error(drive, "irq timeout",
- ide_read_status(drive));
+ hwif->tp_ops->read_status(hwif));
}
drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&ide_lock);
@@ -1323,7 +1323,8 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
*/
do {
if (hwif->irq == irq) {
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
+
if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
/* Try to not flood the console with msgs */
static unsigned long last_msgtime, count;
@@ -1413,7 +1414,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* Whack the status register, just in case
* we have a leftover pending IRQ.
*/
- (void) hwif->INB(hwif->io_ports.status_addr);
+ (void)hwif->tp_ops->read_status(hwif);
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
spin_unlock_irqrestore(&ide_lock, flags);
@@ -1519,6 +1520,7 @@ EXPORT_SYMBOL(ide_do_drive_cmd);
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
{
+ ide_hwif_t *hwif = drive->hwif;
ide_task_t task;
memset(&task, 0, sizeof(task));
@@ -1529,9 +1531,9 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
task.tf.lbah = (bcount >> 8) & 0xff;
ide_tf_dump(drive->name, &task.tf);
- ide_set_irq(drive, 1);
+ hwif->tp_ops->set_irq(hwif, 1);
SELECT_MASK(drive, 0);
- drive->hwif->tf_load(drive, &task);
+ hwif->tp_ops->tf_load(drive, &task);
}
EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
@@ -1543,9 +1545,9 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len)
while (len > 0) {
if (write)
- hwif->output_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
else
- hwif->input_data(drive, NULL, buf, min(4, len));
+ hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
len -= 4;
}
}
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 44aaec256a3..07da5fb9eaf 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -42,18 +42,6 @@ static void ide_outb (u8 val, unsigned long port)
outb(val, port);
}
-static void ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
- outb(addr, port);
-}
-
-void default_hwif_iops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_outb;
- hwif->OUTBSYNC = ide_outbsync;
- hwif->INB = ide_inb;
-}
-
/*
* MMIO operations, typically used for SATA controllers
*/
@@ -68,31 +56,19 @@ static void ide_mm_outb (u8 value, unsigned long port)
writeb(value, (void __iomem *) port);
}
-static void ide_mm_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
-{
- writeb(value, (void __iomem *) port);
-}
-
-void default_hwif_mmiops (ide_hwif_t *hwif)
-{
- hwif->OUTB = ide_mm_outb;
- /* Most systems will need to override OUTBSYNC, alas however
- this one is controller specific! */
- hwif->OUTBSYNC = ide_mm_outbsync;
- hwif->INB = ide_mm_inb;
-}
-
-EXPORT_SYMBOL(default_hwif_mmiops);
-
void SELECT_DRIVE (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
+ ide_task_t task;
if (port_ops && port_ops->selectproc)
port_ops->selectproc(drive);
- hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+ drive->hwif->tp_ops->tf_load(drive, &task);
}
void SELECT_MASK(ide_drive_t *drive, int mask)
@@ -103,7 +79,61 @@ void SELECT_MASK(ide_drive_t *drive, int mask)
port_ops->maskproc(drive, mask);
}
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ else
+ outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.status_addr);
+ else
+ return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+ else
+ return inb(hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -155,8 +185,9 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
tf_outb((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
}
+EXPORT_SYMBOL_GPL(ide_tf_load);
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -188,6 +219,8 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tf_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -214,6 +247,7 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->hob_lbah = tf_inb(io_ports->lbah_addr);
}
}
+EXPORT_SYMBOL_GPL(ide_tf_read);
/*
* Some localbus EIDE interfaces require a special access sequence
@@ -236,8 +270,8 @@ static void ata_vlb_sync(unsigned long port)
* so if an odd len is specified, be sure that there's at least one
* extra byte allocated for the buffer.
*/
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -277,12 +311,13 @@ static void ata_input_data(ide_drive_t *drive, struct request *rq,
insw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_input_data);
/*
* This is used for most PIO data transfers *to* the IDE interface
*/
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
- void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -320,15 +355,50 @@ static void ata_output_data(ide_drive_t *drive, struct request *rq,
outsw(data_addr, buf, len / 2);
}
}
+EXPORT_SYMBOL_GPL(ide_output_data);
+
+u8 ide_read_error(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_FEATURE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.error;
+}
+EXPORT_SYMBOL_GPL(ide_read_error);
-void default_hwif_transport(ide_hwif_t *hwif)
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
{
- hwif->tf_load = ide_tf_load;
- hwif->tf_read = ide_tf_read;
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+ IDE_TFLAG_IN_NSECT;
- hwif->input_data = ata_input_data;
- hwif->output_data = ata_output_data;
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ *bcount = (task.tf.lbah << 8) | task.tf.lbam;
+ *ireason = task.tf.nsect & 3;
}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
+const struct ide_tp_ops default_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
void ide_fix_driveid (struct hd_driveid *id)
{
@@ -483,10 +553,10 @@ int drive_is_ready (ide_drive_t *drive)
* about possible isa-pnp and pci-pnp issues yet.
*/
if (hwif->io_ports.ctl_addr)
- stat = ide_read_altstatus(drive);
+ stat = hwif->tp_ops->read_altstatus(hwif);
else
/* Note: this may clear a pending IRQ!! */
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & BUSY_STAT)
/* drive busy: definitely not interrupting */
@@ -511,24 +581,26 @@ EXPORT_SYMBOL(drive_is_ready);
*/
static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
unsigned long flags;
int i;
u8 stat;
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (stat & BUSY_STAT) {
local_irq_set(flags);
timeout += jiffies;
- while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+ while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
if (time_after(jiffies, timeout)) {
/*
* One last read after the timeout in case
* heavy interrupt load made us not make any
* progress during the timeout..
*/
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!(stat & BUSY_STAT))
break;
@@ -548,7 +620,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
*/
for (i = 0; i < 10; i++) {
udelay(1);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, good, bad)) {
*rstat = stat;
@@ -674,6 +746,7 @@ no_80w:
int ide_driveid_update(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
struct hd_driveid *id;
unsigned long timeout, flags;
u8 stat;
@@ -684,9 +757,9 @@ int ide_driveid_update(ide_drive_t *drive)
*/
SELECT_MASK(drive, 1);
- ide_set_irq(drive, 0);
+ tp_ops->set_irq(hwif, 0);
msleep(50);
- hwif->OUTBSYNC(hwif, WIN_IDENTIFY, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, WIN_IDENTIFY);
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
@@ -695,11 +768,11 @@ int ide_driveid_update(ide_drive_t *drive)
}
msleep(50); /* give drive a breather */
- stat = ide_read_altstatus(drive);
+ stat = tp_ops->read_altstatus(hwif);
} while (stat & BUSY_STAT);
msleep(50); /* wait for IRQ and DRQ_STAT */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
SELECT_MASK(drive, 0);
@@ -713,8 +786,8 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_restore(flags);
return 0;
}
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
- (void)ide_read_status(drive); /* clear drive IRQ */
+ tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+ (void)tp_ops->read_status(hwif); /* clear drive IRQ */
local_irq_enable();
local_irq_restore(flags);
ide_fix_driveid(id);
@@ -735,9 +808,10 @@ int ide_driveid_update(ide_drive_t *drive)
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int error = 0;
u8 stat;
+ ide_task_t task;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_ops) /* check if host supports DMA */
@@ -770,12 +844,19 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
SELECT_DRIVE(drive);
SELECT_MASK(drive, 0);
udelay(1);
- ide_set_irq(drive, 0);
- hwif->OUTB(speed, io_ports->nsect_addr);
- hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
- hwif->OUTBSYNC(hwif, WIN_SETFEATURES, io_ports->command_addr);
+ tp_ops->set_irq(hwif, 0);
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
+ task.tf.feature = SETFEATURES_XFER;
+ task.tf.nsect = speed;
+
+ tp_ops->tf_load(drive, &task);
+
+ tp_ops->exec_command(hwif, WIN_SETFEATURES);
+
if (drive->quirk_list == 2)
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 1);
error = __ide_wait_stat(drive, drive->ready_stat,
BUSY_STAT|DRQ_STAT|ERR_STAT,
@@ -796,8 +877,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
skip:
#ifdef CONFIG_BLK_DEV_IDEDMA
- if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
- drive->using_dma)
+ if (speed >= XFER_SW_DMA_0 && drive->using_dma)
hwif->dma_ops->dma_host_set(drive, 1);
else if (hwif->dma_ops) /* check if host supports DMA */
ide_dma_off_quietly(drive);
@@ -881,7 +961,7 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
spin_lock_irqsave(&ide_lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, cmd);
/*
* Drive takes 400nS to respond, we must avoid the IRQ being
* serviced before that.
@@ -899,7 +979,7 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
- hwif->OUTBSYNC(hwif, WIN_PACKETCMD, hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -924,12 +1004,13 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
*/
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
u8 stat;
SELECT_DRIVE(drive);
udelay (10);
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, 0, BUSY_STAT))
printk("%s: ATAPI reset complete\n", drive->name);
@@ -975,7 +1056,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
}
- tmp = ide_read_status(drive);
+ tmp = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(tmp, 0, BUSY_STAT)) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -1089,8 +1170,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
ide_hwif_t *hwif;
ide_hwgroup_t *hwgroup;
struct ide_io_ports *io_ports;
+ const struct ide_tp_ops *tp_ops;
const struct ide_port_ops *port_ops;
- u8 ctl;
spin_lock_irqsave(&ide_lock, flags);
hwif = HWIF(drive);
@@ -1098,6 +1179,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
io_ports = &hwif->io_ports;
+ tp_ops = hwif->tp_ops;
+
/* We must not reset with running handlers */
BUG_ON(hwgroup->handler != NULL);
@@ -1106,7 +1189,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+ tp_ops->exec_command(hwif, WIN_SRST);
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
@@ -1135,16 +1218,15 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* immediate interrupt due to the edge transition it produces.
* This single interrupt gives us a "fast poll" for drives that
* recover from reset very quickly, saving us the first 50ms wait time.
+ *
+ * TODO: add ->softreset method and stop abusing ->set_irq
*/
/* set SRST and nIEN */
- hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS | 6, io_ports->ctl_addr);
+ tp_ops->set_irq(hwif, 4);
/* more than enough time */
udelay(10);
- if (drive->quirk_list == 2)
- ctl = ATA_DEVCTL_OBS; /* clear SRST and nIEN */
- else
- ctl = ATA_DEVCTL_OBS | 2; /* clear SRST, leave nIEN */
- hwif->OUTBSYNC(hwif, ctl, io_ports->ctl_addr);
+ /* clear SRST, leave nIEN (unless device is on the quirk list) */
+ tp_ops->set_irq(hwif, drive->quirk_list == 2);
/* more than enough time */
udelay(10);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1189,7 +1271,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
* about locking issues (2.5 work ?).
*/
mdelay(1);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if ((stat & BUSY_STAT) == 0)
return 0;
/*
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 13af72f09ec..97fefabea8b 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -266,22 +266,11 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
rate = ide_rate_filter(drive, rate);
+ BUG_ON(rate < XFER_PIO_0);
+
if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
return ide_set_pio_mode(drive, rate);
- /*
- * TODO: transfer modes 0x00-0x07 passed from the user-space are
- * currently handled here which needs fixing (please note that such
- * case could happen iff the transfer mode has already been set on
- * the device by ide-proc.c::set_xfer_rate()).
- */
- if (rate < XFER_PIO_0) {
- if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
- return ide_set_dma_mode(drive, rate);
- else
- return ide_config_drive_speed(drive, rate);
- }
-
return ide_set_dma_mode(drive, rate);
}
@@ -336,7 +325,7 @@ static void ide_dump_sector(ide_drive_t *drive)
else
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
- drive->hwif->tf_read(drive, &task);
+ drive->hwif->tp_ops->tf_read(drive, &task);
if (lba48 || (tf->device & ATA_LBA))
printk(", LBAsect=%llu",
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 03f2ef5470a..bac9b392b68 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -29,9 +29,10 @@ static struct pnp_device_id idepnp_devices[] = {
static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
unsigned long base, ctl;
+ int rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
@@ -59,31 +60,25 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
hw.irq = pnp_irq(dev, 0);
hw.chipset = ide_generic;
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
+ rc = ide_host_add(NULL, hws, &host);
+ if (rc)
+ goto out;
- ide_init_port_hw(hwif, &hw);
-
- pnp_set_drvdata(dev, hwif);
-
- ide_device_add(idx, NULL);
-
- return 0;
- }
+ pnp_set_drvdata(dev, host);
+ return 0;
+out:
release_region(ctl, 1);
release_region(base, 8);
- return -1;
+ return rc;
}
static void idepnp_remove(struct pnp_dev *dev)
{
- ide_hwif_t *hwif = pnp_get_drvdata(dev);
+ struct ide_host *host = pnp_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
release_region(pnp_port_start(dev, 1), 1);
release_region(pnp_port_start(dev, 0), 8);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 235ebdb29b2..4aa76c45375 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -39,8 +39,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
/**
* generic_id - add a generic drive id
* @drive: drive to make an ID block for
@@ -126,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
id = drive->id;
/* read 512 bytes of id info */
- hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
drive->id_read = 1;
local_irq_enable();
@@ -267,6 +265,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int use_altstatus = 0, rc;
unsigned long timeout;
u8 s = 0, a = 0;
@@ -275,8 +274,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
msleep(50);
if (io_ports->ctl_addr) {
- a = ide_read_altstatus(drive);
- s = ide_read_status(drive);
+ a = tp_ops->read_altstatus(hwif);
+ s = tp_ops->read_status(hwif);
if ((a ^ s) & ~INDEX_STAT)
/* ancient Seagate drives, broken interfaces */
printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
@@ -290,12 +289,18 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* set features register for atapi
* identify command to be sure of reply
*/
- if ((cmd == WIN_PIDENTIFY))
- /* disable dma & overlap */
- hwif->OUTB(0, io_ports->feature_addr);
+ if (cmd == WIN_PIDENTIFY) {
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ /* disable DMA & overlap */
+ task.tf_flags = IDE_TFLAG_OUT_FEATURE;
+
+ tp_ops->tf_load(drive, &task);
+ }
/* ask drive for ID */
- hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, cmd);
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies;
@@ -306,13 +311,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
}
/* give drive a breather */
msleep(50);
- s = use_altstatus ? ide_read_altstatus(drive)
- : ide_read_status(drive);
+ s = use_altstatus ? tp_ops->read_altstatus(hwif)
+ : tp_ops->read_status(hwif);
} while (s & BUSY_STAT);
/* wait for IRQ and DRQ_STAT */
msleep(50);
- s = ide_read_status(drive);
+ s = tp_ops->read_status(hwif);
if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
unsigned long flags;
@@ -324,7 +329,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
local_irq_restore(flags);
} else {
/* drive refused ID */
@@ -346,6 +351,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
static int try_to_identify (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int retval;
int autoprobe = 0;
unsigned long cookie = 0;
@@ -361,7 +367,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
autoprobe = 1;
cookie = probe_irq_on();
}
- ide_set_irq(drive, autoprobe);
+ tp_ops->set_irq(hwif, autoprobe);
}
retval = actual_try_to_identify(drive, cmd);
@@ -369,9 +375,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
if (autoprobe) {
int irq;
- ide_set_irq(drive, 0);
+ tp_ops->set_irq(hwif, 0);
/* clear drive IRQ */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
udelay(5);
irq = probe_irq_off(cookie);
if (!hwif->irq) {
@@ -396,7 +402,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
do {
msleep(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if ((stat & BUSY_STAT) == 0)
return 0;
} while (time_before(jiffies, timeout));
@@ -404,6 +410,18 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
return 1;
}
+static u8 ide_read_device(ide_drive_t *drive)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_DEVICE;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ return task.tf.device;
+}
+
/**
* do_probe - probe an IDE device
* @drive: drive to probe
@@ -428,7 +446,7 @@ static int ide_busy_sleep(ide_hwif_t *hwif)
static int do_probe (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
- struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int rc;
u8 stat;
@@ -449,8 +467,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- if (hwif->INB(io_ports->device_addr) != drive->select.all &&
- !drive->present) {
+
+ if (ide_read_device(drive) != drive->select.all && !drive->present) {
if (drive->select.b.unit != 0) {
/* exit with drive0 selected */
SELECT_DRIVE(&hwif->drives[0]);
@@ -461,7 +479,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
return 3;
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
drive->present || cmd == WIN_PIDENTIFY) {
@@ -471,7 +489,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
rc = try_to_identify(drive,cmd);
}
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (stat == (BUSY_STAT | READY_STAT))
return 4;
@@ -482,13 +500,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+ tp_ops->exec_command(hwif, WIN_SRST);
(void)ide_busy_sleep(hwif);
rc = try_to_identify(drive, cmd);
}
/* ensure drive IRQ is clear */
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (rc == 1)
printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
@@ -502,7 +520,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
SELECT_DRIVE(&hwif->drives[0]);
msleep(50);
/* ensure drive irq is clear */
- (void)ide_read_status(drive);
+ (void)tp_ops->read_status(hwif);
}
return rc;
}
@@ -513,12 +531,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
static void enable_nest (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
printk("%s: enabling %s -- ", hwif->name, drive->id->model);
SELECT_DRIVE(drive);
msleep(50);
- hwif->OUTBSYNC(hwif, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
if (ide_busy_sleep(hwif)) {
printk(KERN_CONT "failed (timeout)\n");
@@ -527,7 +546,7 @@ static void enable_nest (ide_drive_t *drive)
msleep(50);
- stat = ide_read_status(drive);
+ stat = tp_ops->read_status(hwif);
if (!OK_STAT(stat, 0, BAD_STAT))
printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
@@ -619,7 +638,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
return drive->present;
}
-static void hwif_release_dev (struct device *dev)
+static void hwif_release_dev(struct device *dev)
{
ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
@@ -709,7 +728,7 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
/* Ignore disks that we will not probe for later. */
if (!drive->noprobe || drive->present) {
SELECT_DRIVE(drive);
- ide_set_irq(drive, 1);
+ hwif->tp_ops->set_irq(hwif, 1);
mdelay(2);
rc = ide_wait_not_busy(hwif, 35000);
if (rc)
@@ -971,6 +990,45 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
mutex_unlock(&ide_cfg_mtx);
}
+static ide_hwif_t *ide_ports[MAX_HWIFS];
+
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+ ide_ports[hwif->index] = NULL;
+
+ spin_lock_irq(&ide_lock);
+ /*
+ * Remove us from the hwgroup, and free
+ * the hwgroup if we were the only member
+ */
+ if (hwif->next == hwif) {
+ BUG_ON(hwgroup->hwif != hwif);
+ kfree(hwgroup);
+ } else {
+ /* There is another interface in hwgroup.
+ * Unlink us, and set hwgroup->drive and ->hwif to
+ * something sane.
+ */
+ ide_hwif_t *g = hwgroup->hwif;
+
+ while (g->next != hwif)
+ g = g->next;
+ g->next = hwif->next;
+ if (hwgroup->hwif == hwif) {
+ /* Chose a random hwif for hwgroup->hwif.
+ * It's guaranteed that there are no drives
+ * left in the hwgroup.
+ */
+ BUG_ON(hwgroup->drive != NULL);
+ hwgroup->hwif = g;
+ }
+ BUG_ON(hwgroup->hwif == hwif);
+ }
+ spin_unlock_irq(&ide_lock);
+}
+
/*
* This routine sets up the irq for an ide interface, and creates a new
* hwgroup for the irq/hwif if none was previously assigned.
@@ -998,8 +1056,9 @@ static int init_irq (ide_hwif_t *hwif)
* Group up with any other hwifs that share our irq(s).
*/
for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *h = &ide_hwifs[index];
- if (h->hwgroup) { /* scan only initialized hwif's */
+ ide_hwif_t *h = ide_ports[index];
+
+ if (h && h->hwgroup) { /* scan only initialized ports */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
if (hwif->chipset != ide_pci ||
@@ -1053,6 +1112,8 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->timer.data = (unsigned long) hwgroup;
}
+ ide_ports[hwif->index] = hwif;
+
/*
* Allocate the irq, if not already obtained for another hwif
*/
@@ -1066,8 +1127,7 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
- /* clear nIEN */
- hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS, io_ports->ctl_addr);
+ hwif->tp_ops->set_irq(hwif, 1);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
goto out_unlink;
@@ -1345,6 +1405,9 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
hwif->host_flags |= d->host_flags;
hwif->pio_mask = d->pio_mask;
+ if (d->tp_ops)
+ hwif->tp_ops = d->tp_ops;
+
/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
hwif->port_ops = d->port_ops;
@@ -1363,6 +1426,7 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if (rc < 0) {
printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+ hwif->dma_base = 0;
hwif->swdma_mask = 0;
hwif->mwdma_mask = 0;
hwif->ultra_mask = 0;
@@ -1446,18 +1510,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
return rc;
}
+static unsigned int ide_indexes;
+
/**
- * ide_find_port_slot - find free ide_hwifs[] slot
+ * ide_find_port_slot - find free port slot
* @d: IDE port info
*
- * Return the new hwif. If we are out of free slots return NULL.
+ * Return the new port slot index or -ENOENT if we are out of free slots.
*/
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+static int ide_find_port_slot(const struct ide_port_info *d)
{
- ide_hwif_t *hwif;
- int i;
+ int idx = -ENOENT;
u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+ u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;;
/*
* Claim an unassigned slot.
@@ -1469,51 +1535,106 @@ ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
* Unless there is a bootable card that does not use the standard
* ports 0x1f0/0x170 (the ide0/ide1 defaults).
*/
- if (bootable) {
- i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
-
- for (; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
- }
+ mutex_lock(&ide_cfg_mtx);
+ if (MAX_HWIFS == 1) {
+ if (ide_indexes == 0 && i == 0)
+ idx = 1;
} else {
- for (i = 2; i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
+ if (bootable) {
+ if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | i);
+ } else {
+ if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+ idx = ffz(ide_indexes | 3);
+ else if ((ide_indexes & 3) != 3)
+ idx = ffz(ide_indexes);
}
- for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
- hwif = &ide_hwifs[i];
- if (hwif->chipset == ide_unknown)
- goto out_found;
+ }
+ if (idx >= 0)
+ ide_indexes |= (1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+
+ return idx;
+}
+
+static void ide_free_port_slot(int idx)
+{
+ mutex_lock(&ide_cfg_mtx);
+ ide_indexes &= ~(1 << idx);
+ mutex_unlock(&ide_cfg_mtx);
+}
+
+struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
+ hw_regs_t **hws)
+{
+ struct ide_host *host;
+ int i;
+
+ host = kzalloc(sizeof(*host), GFP_KERNEL);
+ if (host == NULL)
+ return NULL;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ ide_hwif_t *hwif;
+ int idx;
+
+ if (hws[i] == NULL)
+ continue;
+
+ hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+ if (hwif == NULL)
+ continue;
+
+ idx = ide_find_port_slot(d);
+ if (idx < 0) {
+ printk(KERN_ERR "%s: no free slot for interface\n",
+ d ? d->name : "ide");
+ kfree(hwif);
+ continue;
}
+
+ ide_init_port_data(hwif, idx);
+
+ host->ports[i] = hwif;
+ host->n_ports++;
}
- printk(KERN_ERR "%s: no free slot for interface\n",
- d ? d->name : "ide");
+ if (host->n_ports == 0) {
+ kfree(host);
+ return NULL;
+ }
- return NULL;
+ return host;
+}
+EXPORT_SYMBOL_GPL(ide_host_alloc_all);
+
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+{
+ hw_regs_t *hws_all[MAX_HWIFS];
+ int i;
-out_found:
- ide_init_port_data(hwif, i);
- return hwif;
+ for (i = 0; i < MAX_HWIFS; i++)
+ hws_all[i] = (i < 4) ? hws[i] : NULL;
+
+ return ide_host_alloc_all(d, hws_all);
}
-EXPORT_SYMBOL_GPL(ide_find_port_slot);
+EXPORT_SYMBOL_GPL(ide_host_alloc);
-int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
+ hw_regs_t **hws)
{
ide_hwif_t *hwif, *mate = NULL;
- int i, rc = 0;
+ int i, j = 0;
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff) {
+ hwif = host->ports[i];
+
+ if (hwif == NULL) {
mate = NULL;
continue;
}
- hwif = &ide_hwifs[idx[i]];
-
+ ide_init_port_hw(hwif, hws[i]);
ide_port_apply_params(hwif);
if (d == NULL) {
@@ -1534,10 +1655,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (ide_probe_port(hwif) == 0)
hwif->present = 1;
@@ -1551,19 +1672,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif_init(hwif) == 0) {
printk(KERN_INFO "%s: failed to initialize IDE "
"interface\n", hwif->name);
hwif->present = 0;
- rc = -1;
continue;
}
+ j++;
+
if (hwif->present)
ide_port_setup_devices(hwif);
@@ -1574,10 +1696,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
if (hwif->chipset == ide_unknown)
hwif->chipset = ide_generic;
@@ -1587,10 +1709,10 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
}
for (i = 0; i < MAX_HWIFS; i++) {
- if (idx[i] == 0xff)
- continue;
+ hwif = host->ports[i];
- hwif = &ide_hwifs[idx[i]];
+ if (hwif == NULL)
+ continue;
ide_sysfs_register_port(hwif);
ide_proc_register_port(hwif);
@@ -1599,21 +1721,64 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
ide_proc_port_register_devices(hwif);
}
- return rc;
+ return j ? 0 : -1;
}
-EXPORT_SYMBOL_GPL(ide_device_add_all);
+EXPORT_SYMBOL_GPL(ide_host_register);
-int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
+ struct ide_host **hostp)
{
- u8 idx_all[MAX_HWIFS];
+ struct ide_host *host;
+ int rc;
+
+ host = ide_host_alloc(d, hws);
+ if (host == NULL)
+ return -ENOMEM;
+
+ rc = ide_host_register(host, d, hws);
+ if (rc) {
+ ide_host_free(host);
+ return rc;
+ }
+
+ if (hostp)
+ *hostp = host;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_host_add);
+
+void ide_host_free(struct ide_host *host)
+{
+ ide_hwif_t *hwif;
int i;
- for (i = 0; i < MAX_HWIFS; i++)
- idx_all[i] = (i < 4) ? idx[i] : 0xff;
+ for (i = 0; i < MAX_HWIFS; i++) {
+ hwif = host->ports[i];
- return ide_device_add_all(idx_all, d);
+ if (hwif == NULL)
+ continue;
+
+ ide_free_port_slot(hwif->index);
+ kfree(hwif);
+ }
+
+ kfree(host);
}
-EXPORT_SYMBOL_GPL(ide_device_add);
+EXPORT_SYMBOL_GPL(ide_host_free);
+
+void ide_host_remove(struct ide_host *host)
+{
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (host->ports[i])
+ ide_unregister(host->ports[i]);
+ }
+
+ ide_host_free(host);
+}
+EXPORT_SYMBOL_GPL(ide_host_remove);
void ide_port_scan(ide_hwif_t *hwif)
{
@@ -1634,11 +1799,10 @@ void ide_port_scan(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_port_scan);
-static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
- const struct ide_port_info *d,
+static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+ u8 port_no, const struct ide_port_info *d,
unsigned long config)
{
- ide_hwif_t *hwif;
unsigned long base, ctl;
int irq;
@@ -1668,33 +1832,25 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
ide_std_init_ports(hw, base, ctl);
hw->irq = irq;
hw->chipset = d->chipset;
+ hw->config = config;
- hwif = ide_find_port_slot(d);
- if (hwif) {
- ide_init_port_hw(hwif, hw);
- if (config)
- hwif->config_data = config;
- idx[port_no] = hwif->index;
- }
+ hws[port_no] = hw;
}
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
memset(&hw, 0, sizeof(hw));
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
- ide_legacy_init_one(idx, &hw[0], 0, d, config);
- ide_legacy_init_one(idx, &hw[1], 1, d, config);
+ ide_legacy_init_one(hws, &hw[0], 0, d, config);
+ ide_legacy_init_one(hws, &hw[1], 1, d, config);
- if (idx[0] == 0xff && idx[1] == 0xff &&
+ if (hws[0] == NULL && hws[1] == NULL &&
(d->host_flags & IDE_HFLAG_SINGLE))
return -ENOENT;
- ide_device_add(idx, d);
-
- return 0;
+ return ide_host_add(d, hws, NULL);
}
EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 8af88bf0969..151c91e933d 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -345,7 +345,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
ide_task_t task;
int err;
- if (arg < 0 || arg > 70)
+ if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
return -EINVAL;
memset(&task, 0, sizeof(task));
@@ -357,7 +357,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
err = ide_no_data_taskfile(drive, &task);
- if (!err && arg) {
+ if (!err) {
ide_set_xfer_rate(drive, (u8) arg);
ide_driveid_update(drive);
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index b711ab96e28..6962ca4891a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -195,23 +195,6 @@ enum {
#define IDETAPE_BLOCK_DESCRIPTOR 0
#define IDETAPE_CAPABILITIES_PAGE 0x2a
-/* Tape flag bits values. */
-enum {
- IDETAPE_FLAG_IGNORE_DSC = (1 << 0),
- /* 0 When the tape position is unknown */
- IDETAPE_FLAG_ADDRESS_VALID = (1 << 1),
- /* Device already opened */
- IDETAPE_FLAG_BUSY = (1 << 2),
- /* Attempt to auto-detect the current user block size */
- IDETAPE_FLAG_DETECT_BS = (1 << 3),
- /* Currently on a filemark */
- IDETAPE_FLAG_FILEMARK = (1 << 4),
- /* DRQ interrupt device */
- IDETAPE_FLAG_DRQ_INTERRUPT = (1 << 5),
- /* 0 = no tape is loaded, so we don't rewind after ejecting */
- IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6),
-};
-
/*
* Most of our global data which we need to save even as we leave the driver due
* to an interrupt or a timer event is stored in the struct defined below.
@@ -312,8 +295,6 @@ typedef struct ide_tape_obj {
/* Wasted space in each stage */
int excess_bh_size;
- /* Status/Action flags: long for set_bit */
- unsigned long flags;
/* protects the ide-tape queue */
spinlock_t lock;
@@ -398,7 +379,7 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
count = min(
(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
bcount);
- drive->hwif->input_data(drive, NULL, bh->b_data +
+ drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
atomic_read(&bh->b_count), count);
bcount -= count;
atomic_add(count, &bh->b_count);
@@ -424,7 +405,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
return;
}
count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- drive->hwif->output_data(drive, NULL, pc->b_data, count);
+ drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
bcount -= count;
pc->b_data += count;
pc->b_count -= count;
@@ -585,7 +566,6 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
bh = bh->b_reqnext;
kfree(prev_bh);
}
- kfree(tape->merge_bh);
}
static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -665,7 +645,7 @@ static void ide_tape_callback(ide_drive_t *drive)
if (readpos[0] & 0x4) {
printk(KERN_INFO "ide-tape: Block location is unknown"
"to the tape\n");
- clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
uptodate = 0;
} else {
debug_log(DBG_SENSE, "Block Location - %u\n",
@@ -673,7 +653,7 @@ static void ide_tape_callback(ide_drive_t *drive)
tape->partition = readpos[1];
tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]);
- set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+ set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
}
}
@@ -690,7 +670,6 @@ static void idetape_init_pc(struct ide_atapi_pc *pc)
pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
pc->bh = NULL;
pc->b_data = NULL;
- pc->callback = ide_tape_callback;
}
static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -705,7 +684,7 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
{
blk_rq_init(NULL, rq);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = cmd;
+ rq->cmd[13] = cmd;
}
/*
@@ -732,6 +711,7 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
rq->cmd_flags |= REQ_PREEMPT;
rq->buffer = (char *) pc;
rq->rq_disk = tape->disk;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
}
@@ -742,7 +722,6 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
*/
static void idetape_retry_pc(ide_drive_t *drive)
{
- idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc;
struct request *rq;
@@ -750,7 +729,7 @@ static void idetape_retry_pc(ide_drive_t *drive)
pc = idetape_next_pc_storage(drive);
rq = idetape_next_rq_storage(drive);
idetape_create_request_sense_cmd(pc);
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
idetape_queue_pc_head(drive, pc, rq);
}
@@ -887,7 +866,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->error = IDETAPE_ERROR_GENERAL;
}
tape->failed_pc = NULL;
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -927,11 +906,12 @@ static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = tape->pc;
u8 stat;
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & SEEK_STAT) {
if (stat & ERR_STAT) {
@@ -948,14 +928,17 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
pc->error = IDETAPE_ERROR_GENERAL;
tape->failed_pc = NULL;
}
- pc->callback(drive);
+ drive->pc_callback(drive);
return ide_stopped;
}
static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
- struct ide_atapi_pc *pc, unsigned int length,
- struct idetape_bh *bh, u8 opcode)
+ struct ide_atapi_pc *pc, struct request *rq,
+ u8 opcode)
{
+ struct idetape_bh *bh = (struct idetape_bh *)rq->special;
+ unsigned int length = rq->current_nr_sectors;
+
idetape_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
@@ -975,11 +958,14 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
pc->b_data = bh->b_data;
pc->b_count = atomic_read(&bh->b_count);
}
+
+ memcpy(rq->cmd, pc->c, 12);
}
static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct request *rq, sector_t block)
{
+ ide_hwif_t *hwif = drive->hwif;
idetape_tape_t *tape = drive->driver_data;
struct ide_atapi_pc *pc = NULL;
struct request *postponed_rq = tape->postponed_rq;
@@ -1017,17 +1003,17 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
* If the tape is still busy, postpone our request and service
* the other device meanwhile.
*/
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
- if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
if (drive->post_reset == 1) {
- set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+ set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
drive->post_reset = 0;
}
- if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
+ if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
(stat & SEEK_STAT) == 0) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
@@ -1036,7 +1022,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
} else if (time_after(jiffies, tape->dsc_timeout)) {
printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
tape->name);
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
} else {
@@ -1049,35 +1035,29 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
idetape_postpone_request(drive);
return ide_stopped;
}
- if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ if (rq->cmd[13] & REQ_IDETAPE_READ) {
pc = idetape_next_pc_storage(drive);
- ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special,
- READ_6);
+ ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
pc = idetape_next_pc_storage(drive);
- ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
- (struct idetape_bh *)rq->special,
- WRITE_6);
+ ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC1) {
pc = (struct ide_atapi_pc *) rq->buffer;
- rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
- rq->cmd[0] |= REQ_IDETAPE_PC2;
+ rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
+ rq->cmd[13] |= REQ_IDETAPE_PC2;
goto out;
}
- if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+ if (rq->cmd[13] & REQ_IDETAPE_PC2) {
idetape_media_access_finished(drive);
return ide_stopped;
}
BUG();
-out:
- if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags))
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
+out:
return idetape_issue_pc(drive, pc);
}
@@ -1281,8 +1261,9 @@ static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = REQ_IDETAPE_PC1;
+ rq->cmd[13] = REQ_IDETAPE_PC1;
rq->buffer = (char *)pc;
+ memcpy(rq->cmd, pc->c, 12);
error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
blk_put_request(rq);
return error;
@@ -1304,7 +1285,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
int load_attempted = 0;
/* Wait for the tape to become ready */
- set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
timeout += jiffies;
while (time_before(jiffies, timeout)) {
idetape_create_test_unit_ready_cmd(&pc);
@@ -1397,7 +1378,7 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
if (tape->chrdev_dir != IDETAPE_DIR_READ)
return;
- clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+ clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
tape->merge_bh_size = 0;
if (tape->merge_bh != NULL) {
ide_tape_kfree_buffer(tape);
@@ -1465,7 +1446,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd[0] = cmd;
+ rq->cmd[13] = cmd;
rq->rq_disk = tape->disk;
rq->special = (void *)bh;
rq->sector = tape->first_frame;
@@ -1636,7 +1617,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
/* If we are at a filemark, return a read length of 0 */
- if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
return 0;
idetape_init_read(drive);
@@ -1746,7 +1727,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
if (tape->chrdev_dir == IDETAPE_DIR_READ) {
tape->merge_bh_size = 0;
- if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+ if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
++count;
ide_tape_discard_merge_buffer(drive, 0);
}
@@ -1801,7 +1782,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+ if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags))
if (count > tape->blk_size &&
(count % tape->blk_size) == 0)
tape->user_bs_factor = count / tape->blk_size;
@@ -1841,7 +1822,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
tape->merge_bh_size = bytes_read-temp;
}
finish:
- if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+ if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
idetape_space_over_filemarks(drive, MTFSF, 1);
@@ -2027,7 +2008,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
!IDETAPE_LU_LOAD_MASK);
retval = idetape_queue_pc_tail(drive, &pc);
if (!retval)
- clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+ clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
return retval;
case MTNOP:
ide_tape_discard_merge_buffer(drive, 0);
@@ -2050,9 +2031,9 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
mt_count % tape->blk_size)
return -EIO;
tape->user_bs_factor = mt_count / tape->blk_size;
- clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
} else
- set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+ set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
return 0;
case MTSEEK:
ide_tape_discard_merge_buffer(drive, 0);
@@ -2202,20 +2183,20 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
filp->private_data = tape;
- if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+ if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) {
retval = -EBUSY;
goto out_put_tape;
}
retval = idetape_wait_ready(drive, 60 * HZ);
if (retval) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
goto out_put_tape;
}
idetape_read_position(drive);
- if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+ if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags))
(void)idetape_rewind_tape(drive);
/* Read block size and write protect status from drive. */
@@ -2231,7 +2212,7 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
if (tape->write_prot) {
if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
(filp->f_flags & O_ACCMODE) == O_RDWR) {
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
retval = -EROFS;
goto out_put_tape;
}
@@ -2291,7 +2272,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
ide_tape_discard_merge_buffer(drive, 1);
}
- if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+ if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags))
(void) idetape_rewind_tape(drive);
if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
if (tape->door_locked == DOOR_LOCKED) {
@@ -2301,7 +2282,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
}
}
}
- clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+ clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
ide_tape_put(tape);
unlock_kernel();
return 0;
@@ -2464,6 +2445,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
u8 gcw[2];
u16 *ctl = (u16 *)&tape->caps[12];
+ drive->pc_callback = ide_tape_callback;
+
spin_lock_init(&tape->lock);
drive->dsc_overlap = 1;
if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
@@ -2484,7 +2467,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
/* Command packet DRQ type */
if (((gcw[0] & 0x60) >> 5) == 1)
- set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
+ set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
idetape_get_inquiry_results(drive);
idetape_get_mode_sense_results(drive);
@@ -2697,10 +2680,12 @@ static int ide_tape_probe(ide_drive_t *drive)
idetape_setup(drive, tape, minor);
- device_create(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
- device_create(idetape_sysfs_class, &drive->gendev,
- MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor), NULL,
+ "%s", tape->name);
+ device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+ MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+ "n%s", tape->name);
g->fops = &idetape_block_ops;
ide_register_region(g);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 1fbdb746dc8..aeddbbd69e8 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -64,6 +64,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
ide_hwif_t *hwif = HWIF(drive);
struct ide_taskfile *tf = &task->tf;
ide_handler_t *handler = NULL;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
const struct ide_dma_ops *dma_ops = hwif->dma_ops;
if (task->data_phase == TASKFILE_MULTI_IN ||
@@ -80,15 +81,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_dump(drive->name, tf);
- ide_set_irq(drive, 1);
+ tp_ops->set_irq(hwif, 1);
SELECT_MASK(drive, 0);
- hwif->tf_load(drive, task);
+ tp_ops->tf_load(drive, task);
}
switch (task->data_phase) {
case TASKFILE_MULTI_OUT:
case TASKFILE_OUT:
- hwif->OUTBSYNC(hwif, tf->command, hwif->io_ports.command_addr);
+ tp_ops->exec_command(hwif, tf->command);
ndelay(400); /* FIXME */
return pre_task_out_intr(drive, task->rq);
case TASKFILE_MULTI_IN:
@@ -124,7 +125,8 @@ EXPORT_SYMBOL_GPL(do_rw_taskfile);
*/
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, READY_STAT, BAD_STAT))
drive->mult_count = drive->mult_req;
@@ -141,11 +143,16 @@ static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
*/
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
int retries = 5;
u8 stat;
- while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
+ while (1) {
+ stat = hwif->tp_ops->read_status(hwif);
+ if ((stat & BUSY_STAT) == 0 || retries-- == 0)
+ break;
udelay(10);
+ };
if (OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_stopped;
@@ -162,7 +169,8 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
*/
static ide_startstop_t recal_intr(ide_drive_t *drive)
{
- u8 stat = ide_read_status(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_error(drive, "recal_intr", stat);
@@ -174,11 +182,12 @@ static ide_startstop_t recal_intr(ide_drive_t *drive)
*/
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
- ide_task_t *args = HWGROUP(drive)->rq->special;
+ ide_hwif_t *hwif = drive->hwif;
+ ide_task_t *args = hwif->hwgroup->rq->special;
u8 stat;
local_irq_enable_in_hardirq();
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_error(drive, "task_no_data_intr", stat);
@@ -192,6 +201,7 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
+ ide_hwif_t *hwif = drive->hwif;
int retries;
u8 stat;
@@ -200,7 +210,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
* take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
*/
for (retries = 0; retries < 1000; retries++) {
- stat = ide_read_status(drive);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat & BUSY_STAT)
udelay(10);
@@ -255,9 +265,9 @@ static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
/* do the actual data transfer */
if (write)
- hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
else
- hwif->input_data(drive, rq, buf, SECTOR_SIZE);
+ hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM
@@ -383,8 +393,8 @@ static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq
static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ struct request *rq = hwif->hwgroup->rq;
+ u8 stat = hwif->tp_ops->read_status(hwif);
/* Error? */
if (stat & ERR_STAT)
@@ -418,7 +428,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = HWGROUP(drive)->rq;
- u8 stat = ide_read_status(drive);
+ u8 stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return task_error(drive, rq, __func__, stat);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index d4a6b102a77..60f0ca66aa9 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
- * Copyrifht (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
*/
/*
@@ -101,8 +101,7 @@ void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
init_completion(&hwif->gendev_rel_comp);
- default_hwif_iops(hwif);
- default_hwif_transport(hwif);
+ hwif->tp_ops = &default_tp_ops;
ide_port_init_devices_data(hwif);
}
@@ -134,41 +133,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
}
}
-void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-{
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
-
- spin_lock_irq(&ide_lock);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- ide_hwif_t *g = hwgroup->hwif;
-
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
- spin_unlock_irq(&ide_lock);
-}
-
/* Called with ide_lock held. */
static void __ide_port_unregister_devices(ide_hwif_t *hwif)
{
@@ -269,16 +233,9 @@ void ide_unregister(ide_hwif_t *hwif)
if (hwif->dma_base)
ide_release_dma_engine(hwif);
- spin_lock_irq(&ide_lock);
- /* restore hwif data to pristine status */
- ide_init_port_data(hwif, hwif->index);
- spin_unlock_irq(&ide_lock);
-
mutex_unlock(&ide_cfg_mtx);
}
-EXPORT_SYMBOL(ide_unregister);
-
void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
@@ -287,8 +244,8 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
hwif->dev = hw->dev;
hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
hwif->ack_intr = hw->ack_intr;
+ hwif->config_data = hw->config;
}
-EXPORT_SYMBOL_GPL(ide_init_port_hw);
/*
* Locks for IDE setting functionality
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 0497e7f85b0..7c2afa97f41 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -37,6 +37,8 @@
#define CATWEASEL_NUM_HWIFS 3
#define XSURF_NUM_HWIFS 2
+#define MAX_NUM_HWIFS 3
+
/*
* Bases of the IDE interfaces (relative to the board address)
*/
@@ -148,18 +150,14 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init buddha_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
- int i;
-
struct zorro_dev *z = NULL;
u_long buddha_board = 0;
BuddhaType type;
- int buddha_num_hwifs;
+ int buddha_num_hwifs, i;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS;
@@ -221,19 +219,13 @@ fail_base2:
ack_intr = xsurf_ack_intr;
}
- buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+ buddha_setup_ports(&hw[i], base, ctl, irq_port,
+ ack_intr);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[i] = index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
+ ide_host_add(NULL, hws, NULL);
}
return 0;
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 129a812bb57..724f95073d8 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -66,6 +66,27 @@ static void falconide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = falconide_input_data,
+ .output_data = falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+ .tp_ops = &falconide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
static void __init falconide_setup_ports(hw_regs_t *hw)
{
int i;
@@ -91,11 +112,12 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
static int __init falconide_init(void)
{
- hw_regs_t hw;
- ide_hwif_t *hwif;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int rc;
if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
- return 0;
+ return -ENODEV;
printk(KERN_INFO "ide: Falcon IDE controller\n");
@@ -106,23 +128,25 @@ static int __init falconide_init(void)
falconide_setup_ports(&hw);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
- ide_init_port_hw(hwif, &hw);
+ host = ide_host_alloc(&falconide_port_info, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- /* Atari has a byte-swapped IDE interface */
- hwif->input_data = falconide_input_data;
- hwif->output_data = falconide_output_data;
+ ide_get_lock(NULL, NULL);
+ rc = ide_host_register(host, &falconide_port_info, hws);
+ ide_release_lock();
- ide_get_lock(NULL, NULL);
- ide_device_add(idx, NULL);
- ide_release_lock();
- }
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
+err:
+ release_mem_region(ATA_HD_BASE, 0x40);
+ return rc;
}
module_init(falconide_init);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 7e74b20202d..dd5c467d8dd 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -31,6 +31,8 @@
#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
+#define GAYLE_IDEREG_SIZE 0x2000
+
/*
* Offsets from one of the above bases
*/
@@ -56,13 +58,11 @@
#define GAYLE_NUM_HWIFS 1
#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
#define GAYLE_HAS_CONTROL_REG 1
-#define GAYLE_IDEREG_SIZE 0x2000
#else /* CONFIG_BLK_DEV_IDEDOUBLER */
#define GAYLE_NUM_HWIFS 2
#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
GAYLE_NUM_HWIFS-1)
#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
-#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
static int ide_doubler;
module_param_named(doubler, ide_doubler, bool, 0);
@@ -124,8 +124,11 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init gayle_init(void)
{
+ unsigned long phys_base, res_start, res_n;
+ unsigned long base, ctrlport, irqport;
+ ide_ack_intr_t *ack_intr;
int a4000, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_AMIGA)
return -ENODEV;
@@ -148,13 +151,6 @@ found:
#endif
"");
- for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
- unsigned long base, ctrlport, irqport;
- ide_ack_intr_t *ack_intr;
- hw_regs_t hw;
- ide_hwif_t *hwif;
- unsigned long phys_base, res_start, res_n;
-
if (a4000) {
phys_base = GAYLE_BASE_4000;
irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
@@ -168,33 +164,22 @@ found:
* FIXME: we now have selectable modes between mmio v/s iomio
*/
- phys_base += i*GAYLE_NEXT_PORT;
-
res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
res_n = GAYLE_IDEREG_SIZE;
if (!request_mem_region(res_start, res_n, "IDE"))
- continue;
+ return -EBUSY;
- base = (unsigned long)ZTWO_VADDR(phys_base);
+ for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+ base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
- gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
-
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
+ gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
- ide_init_port_hw(hwif, &hw);
-
- idx[i] = index;
- } else
- release_mem_region(res_start, res_n);
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(gayle_init);
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
index 89c8ff0a4d0..c76d55de699 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/legacy/ide-4drives.c
@@ -28,10 +28,8 @@ static const struct ide_port_info ide_4drives_port_info = {
static int __init ide_4drives_init(void)
{
- ide_hwif_t *hwif, *mate;
unsigned long base = 0x1f0, ctl = 0x3f6;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
if (probe_4drives == 0)
return -ENODEV;
@@ -55,21 +53,7 @@ static int __init ide_4drives_init(void)
hw.irq = 14;
hw.chipset = ide_4drives;
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
- }
-
- mate = ide_find_port();
- if (mate) {
- ide_init_port_hw(mate, &hw);
- idx[1] = mate->index;
- }
-
- ide_device_add(idx, &ide_4drives_port_info);
-
- return 0;
+ return ide_host_add(&ide_4drives_port_info, hws, NULL);
}
module_init(ide_4drives_init);
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 27b1e0b7ecb..21bfac13784 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -74,7 +74,7 @@ INT_MODULE_PARM(pc_debug, 0);
typedef struct ide_info_t {
struct pcmcia_device *p_dev;
- ide_hwif_t *hwif;
+ struct ide_host *host;
int ndev;
dev_node_t node;
} ide_info_t;
@@ -132,7 +132,7 @@ static int ide_probe(struct pcmcia_device *link)
static void ide_detach(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ ide_hwif_t *hwif = info->host->ports[0];
unsigned long data_addr, ctl_addr;
DEBUG(0, "ide_detach(0x%p)\n", link);
@@ -157,13 +157,13 @@ static const struct ide_port_info idecs_port_info = {
.host_flags = IDE_HFLAG_NO_DMA,
};
-static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
+static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle)
{
+ struct ide_host *host;
ide_hwif_t *hwif;
- hw_regs_t hw;
- int i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!request_region(io, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -184,30 +184,24 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
hw.chipset = ide_pci;
hw.dev = &handle->dev;
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&idecs_port_info, hws, &host);
+ if (rc)
goto out_release;
- i = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = i;
-
- ide_device_add(idx, &idecs_port_info);
+ hwif = host->ports[0];
if (hwif->present)
- return hwif;
+ return host;
/* retry registration in case device is still spinning up */
for (i = 0; i < 10; i++) {
msleep(100);
ide_port_scan(hwif);
if (hwif->present)
- return hwif;
+ return host;
}
- return hwif;
+ return host;
out_release:
release_region(ctl, 1);
@@ -239,7 +233,7 @@ static int ide_config(struct pcmcia_device *link)
cistpl_cftable_entry_t *cfg;
int pass, last_ret = 0, last_fn = 0, is_kme = 0;
unsigned long io_base, ctl_base;
- ide_hwif_t *hwif;
+ struct ide_host *host;
DEBUG(0, "ide_config(0x%p)\n", link);
@@ -334,21 +328,21 @@ static int ide_config(struct pcmcia_device *link)
if (is_kme)
outb(0x81, ctl_base+1);
- hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
- if (hwif == NULL && link->io.NumPorts1 == 0x20) {
+ host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+ if (host == NULL && link->io.NumPorts1 == 0x20) {
outb(0x02, ctl_base + 0x10);
- hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
+ host = idecs_register(io_base + 0x10, ctl_base + 0x10,
link->irq.AssignedIRQ, link);
}
- if (hwif == NULL)
+ if (host == NULL)
goto failed;
info->ndev = 1;
- sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
- info->node.major = hwif->major;
+ sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
+ info->node.major = host->ports[0]->major;
info->node.minor = 0;
- info->hwif = hwif;
+ info->host = host;
link->dev_node = &info->node;
printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
@@ -379,15 +373,15 @@ failed:
static void ide_release(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- ide_hwif_t *hwif = info->hwif;
+ struct ide_host *host = info->host;
DEBUG(0, "ide_release(0x%p)\n", link);
- if (info->ndev) {
+ if (info->ndev)
/* FIXME: if this fails we need to queue the cleanup somehow
-- need to investigate the required PCMCIA magic */
- ide_unregister(hwif);
- }
+ ide_host_remove(host);
+
info->ndev = 0;
pcmcia_disable_device(link);
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index a249562b34b..051b4ab0f35 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -52,12 +52,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_alt, *res_irq;
void __iomem *base, *alt_base;
- ide_hwif_t *hwif;
struct pata_platform_info *pdata;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- int ret = 0;
- int mmio = 0;
- hw_regs_t hw;
+ struct ide_host *host;
+ int ret = 0, mmio = 0;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
struct ide_port_info d = platform_ide_port_info;
pdata = pdev->dev.platform_data;
@@ -94,28 +92,18 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
res_alt->start, res_alt->end - res_alt->start + 1);
}
- hwif = ide_find_port();
- if (!hwif) {
- ret = -ENODEV;
- goto out;
- }
-
memset(&hw, 0, sizeof(hw));
plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
hw.dev = &pdev->dev;
- ide_init_port_hw(hwif, &hw);
-
- if (mmio) {
+ if (mmio)
d.host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
- }
- idx[0] = hwif->index;
-
- ide_device_add(idx, &d);
+ ret = ide_host_add(&d, hws, &host);
+ if (ret)
+ goto out;
- platform_set_drvdata(pdev, hwif);
+ platform_set_drvdata(pdev, host);
return 0;
@@ -125,9 +113,9 @@ out:
static int __devexit plat_ide_remove(struct platform_device *pdev)
{
- ide_hwif_t *hwif = pdev->dev.driver_data;
+ struct ide_host *host = pdev->dev.driver_data;
- ide_unregister(hwif);
+ ide_host_remove(host);
return 0;
}
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index 0a6195bcfed..a0bb167980e 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -91,11 +91,10 @@ static const char *mac_ide_name[] =
static int __init macide_init(void)
{
- ide_hwif_t *hwif;
ide_ack_intr_t *ack_intr;
unsigned long base;
int irq;
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!MACH_IS_MAC)
return -ENODEV;
@@ -125,17 +124,7 @@ static int __init macide_init(void)
macide_setup_ports(&hw, base, irq, ack_intr);
- hwif = ide_find_port();
- if (hwif) {
- u8 index = hwif->index;
- u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
- ide_init_port_hw(hwif, &hw);
-
- ide_device_add(idx, NULL);
- }
-
- return 0;
+ return ide_host_add(NULL, hws, NULL);
}
module_init(macide_init);
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 9c2b9d078f6..4abd8fc7819 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -96,6 +96,27 @@ static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = q40ide_input_data,
+ .output_data = q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+ .tp_ops = &q40ide_tp_ops,
+ .host_flags = IDE_HFLAG_NO_DMA,
+};
+
/*
* the static array is needed to have the name reported in /proc/ioports,
* hwif->name unfortunately isn't available yet
@@ -111,9 +132,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
static int __init q40ide_init(void)
{
int i;
- ide_hwif_t *hwif;
- const char *name;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
if (!MACH_IS_Q40)
return -ENODEV;
@@ -121,9 +140,8 @@ static int __init q40ide_init(void)
printk(KERN_INFO "ide: Q40 IDE controller\n");
for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
- hw_regs_t hw;
+ const char *name = q40_ide_names[i];
- name = q40_ide_names[i];
if (!request_region(pcide_bases[i], 8, name)) {
printk("could not reserve ports %lx-%lx for %s\n",
pcide_bases[i],pcide_bases[i]+8,name);
@@ -135,26 +153,13 @@ static int __init q40ide_init(void)
release_region(pcide_bases[i], 8);
continue;
}
- q40_ide_setup_ports(&hw, pcide_bases[i],
- NULL,
-// m68kide_iops,
+ q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
q40ide_default_irq(pcide_bases[i]));
- hwif = ide_find_port();
- if (hwif) {
- ide_init_port_hw(hwif, &hw);
-
- /* Q40 has a byte-swapped IDE interface */
- hwif->input_data = q40ide_input_data;
- hwif->output_data = q40ide_output_data;
-
- idx[i] = hwif->index;
- }
+ hws[i] = &hw[i];
}
- ide_device_add(idx, NULL);
-
- return 0;
+ return ide_host_add(&q40ide_port_info, hws, NULL);
}
module_init(q40ide_init);
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 48d57cae63c..11b7f61aae4 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -519,6 +519,23 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
*ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
}
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = au1xxx_input_data,
+ .output_data = au1xxx_output_data,
+};
+#endif
+
static const struct ide_port_ops au1xxx_port_ops = {
.set_pio_mode = au1xxx_set_pio_mode,
.set_dma_mode = auide_set_dma_mode,
@@ -526,6 +543,9 @@ static const struct ide_port_ops au1xxx_port_ops = {
static const struct ide_port_info au1xxx_port_info = {
.init_dma = auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+ .tp_ops = &au1xxx_tp_ops,
+#endif
.port_ops = &au1xxx_port_ops,
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
.dma_ops = &au1xxx_dma_ops,
@@ -543,11 +563,10 @@ static int au_ide_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_hwif_t *hwif;
struct resource *res;
+ struct ide_host *host;
int ret = 0;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
char *mode = "MWDMA2";
@@ -584,36 +603,19 @@ static int au_ide_probe(struct device *dev)
goto out;
}
- hwif = ide_find_port();
- if (hwif == NULL) {
- ret = -ENOENT;
- goto out;
- }
-
memset(&hw, 0, sizeof(hw));
auide_setup_ports(&hw, ahwif);
hw.irq = ahwif->irq;
hw.dev = dev;
hw.chipset = ide_au1xxx;
- ide_init_port_hw(hwif, &hw);
-
- /* If the user has selected DDMA assisted copies,
- then set up a few local I/O function entry points
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
- hwif->input_data = au1xxx_input_data;
- hwif->output_data = au1xxx_output_data;
-#endif
-
- auide_hwif.hwif = hwif;
-
- idx[0] = hwif->index;
+ ret = ide_host_add(&au1xxx_port_info, hws, &host);
+ if (ret)
+ goto out;
- ide_device_add(idx, &au1xxx_port_info);
+ auide_hwif.hwif = host->ports[0];
- dev_set_drvdata(dev, hwif);
+ dev_set_drvdata(dev, host);
printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
@@ -625,10 +627,10 @@ static int au_ide_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
- ide_hwif_t *hwif = dev_get_drvdata(dev);
+ struct ide_host *host = dev_get_drvdata(dev);
_auide_hwif *ahwif = &auide_hwif;
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void *)ahwif->regbase);
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 9f1212cc4ae..badf79fc9e3 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -72,12 +72,11 @@ static const struct ide_port_info swarm_port_info = {
*/
static int __devinit swarm_ide_probe(struct device *dev)
{
- ide_hwif_t *hwif;
u8 __iomem *base;
+ struct ide_host *host;
phys_t offset, size;
- hw_regs_t hw;
- int i;
- u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+ int i, rc;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!SIBYTE_HAVE_IDE)
return -ENODEV;
@@ -116,26 +115,17 @@ static int __devinit swarm_ide_probe(struct device *dev)
hw.irq = K_INT_GB_IDE;
hw.chipset = ide_generic;
- hwif = ide_find_port_slot(&swarm_port_info);
- if (hwif == NULL)
+ rc = ide_host_add(&swarm_port_info, hws, &host);
+ if (rc)
goto err;
- ide_init_port_hw(hwif, &hw);
-
- /* Setup MMIO ops. */
- default_hwif_mmiops(hwif);
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, &swarm_port_info);
-
- dev_set_drvdata(dev, hwif);
+ dev_set_drvdata(dev, host);
return 0;
err:
release_resource(&swarm_ide_resource);
iounmap(base);
- return -ENOMEM;
+ return rc;
}
static struct device_driver swarm_ide_driver = {
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index ae7a4329a58..fbc43e121e6 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -195,7 +195,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.host_flags = IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_ATAPI_DMA |
IDE_HFLAG_NO_DSC |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -205,7 +204,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -216,7 +214,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_NON_BOOTABLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -226,7 +223,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.init_chipset = init_chipset_aec62xx,
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -237,7 +233,6 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.port_ops = &atp86x_port_ops,
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 80d19c0eb78..5ef7817ac64 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -471,7 +471,15 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
if (!hwif->channel)
@@ -483,7 +491,7 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 0bfcdd0e77b..ef7d971031e 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -218,7 +218,6 @@ static const struct ide_port_ops amd_port_ops = {
#define IDE_HFLAGS_AMD \
(IDE_HFLAG_PIO_NO_BLACKLIST | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_POST_SET_MODE | \
IDE_HFLAG_IO_32BIT | \
IDE_HFLAG_UNMASK_IRQS)
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index 1ad1e23e310..e6c62006ca1 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -181,11 +181,6 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
static DEFINE_SPINLOCK(cmd640_lock);
/*
- * These are initialized to point at the devices we control
- */
-static ide_hwif_t *cmd_hwif0, *cmd_hwif1;
-
-/*
* Interface to access cmd640x registers
*/
static unsigned int cmd640_key;
@@ -717,8 +712,7 @@ static int __init cmd640x_init(void)
int second_port_cmd640 = 0, rc;
const char *bus_type, *port2;
u8 b, cfr;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw[2];
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
if (cmd640_vlb && probe_for_cmd640_vlb()) {
bus_type = "VLB";
@@ -781,15 +775,10 @@ static int __init cmd640x_init(void)
printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
"\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
- cmd_hwif0 = ide_find_port();
-
/*
* Initialize data for primary port
*/
- if (cmd_hwif0) {
- ide_init_port_hw(cmd_hwif0, &hw[0]);
- idx[0] = cmd_hwif0->index;
- }
+ hws[0] = &hw[0];
/*
* Ensure compatibility by always using the slowest timings
@@ -829,13 +818,9 @@ static int __init cmd640x_init(void)
/*
* Initialize data for secondary cmd640 port, if enabled
*/
- if (second_port_cmd640) {
- cmd_hwif1 = ide_find_port();
- if (cmd_hwif1) {
- ide_init_port_hw(cmd_hwif1, &hw[1]);
- idx[1] = cmd_hwif1->index;
- }
- }
+ if (second_port_cmd640)
+ hws[1] = &hw[1];
+
printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
second_port_cmd640 ? "" : "not ", port2);
@@ -843,9 +828,7 @@ static int __init cmd640x_init(void)
cmd640_dump_regs();
#endif
- ide_device_add(idx, &cmd640_port_info);
-
- return 1;
+ return ide_host_add(&cmd640_port_info, hws, NULL);
}
module_param_named(probe_vlb, cmd640_vlb, bool, 0);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index cfa784bacf4..ce58bfcdb3c 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -262,7 +262,7 @@ static int cmd648_dma_test_irq(ide_drive_t *drive)
unsigned long base = hwif->dma_base - (hwif->channel * 8);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 mrdmode = inb(base + 1);
#ifdef DEBUG
@@ -286,7 +286,7 @@ static int cmd64x_dma_test_irq(ide_drive_t *drive)
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
@@ -317,13 +317,13 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA status */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* read DMA command state */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* clear the INTR & ERROR bits */
- outb(dma_stat | 6, hwif->dma_status);
+ outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 992b1cf8db6..b03d8ae947e 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -62,8 +62,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
- /* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
-
/* 8bit CAT/CRT - 8bit command timing for channel */
pci_write_config_byte(pdev, 0x62 + controller,
(cs5520_pio_clocks[pio].recovery << 4) |
@@ -89,46 +87,17 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
cs5520_set_pio_mode(drive, 0);
}
-/*
- * We wrap the DMA activate to set the vdma flag. This is needed
- * so that the IDE DMA layer issues PIO not DMA commands over the
- * DMA channel
- *
- * ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
- */
-
-static void cs5520_dma_host_set(ide_drive_t *drive, int on)
-{
- drive->vdma = on;
- ide_dma_host_set(drive, on);
-}
-
static const struct ide_port_ops cs5520_port_ops = {
.set_pio_mode = cs5520_set_pio_mode,
.set_dma_mode = cs5520_set_dma_mode,
};
-static const struct ide_dma_ops cs5520_dma_ops = {
- .dma_host_set = cs5520_dma_host_set,
- .dma_setup = ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = __ide_dma_end,
- .dma_test_irq = ide_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timeout = ide_dma_timeout,
-};
-
-/* FIXME: VDMA is disabled because it caused system hangs */
#define DECLARE_CS_DEV(name_str) \
{ \
.name = name_str, \
.port_ops = &cs5520_port_ops, \
- .dma_ops = &cs5520_dma_ops, \
.host_flags = IDE_HFLAG_ISA_PORTS | \
- IDE_HFLAG_CS5520 | \
- IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE, \
+ IDE_HFLAG_CS5520, \
.pio_mask = ATA_PIO4, \
}
@@ -146,7 +115,7 @@ static const struct ide_port_info cyrix_chipsets[] __devinitdata = {
static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
ide_setup_pci_noise(dev, d);
@@ -168,11 +137,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
* do all the device setup for us
*/
- ide_pci_setup_ports(dev, d, 14, &idx[0]);
-
- ide_device_add(idx, d);
+ ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
- return 0;
+ return ide_host_add(d, hws, NULL);
}
static const struct pci_device_id cs5520_pci_tbl[] = {
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index dc97c48623f..5404fe4f701 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -171,8 +171,7 @@ static const struct ide_port_ops cs5535_port_ops = {
static const struct ide_port_info cs5535_chipset __devinitdata = {
.name = "CS5535",
.port_ops = &cs5535_port_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 0106e2a2df7..f84bfb4f600 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -56,11 +56,10 @@ static const struct ide_port_info delkin_cb_port_info = {
static int __devinit
delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
+ struct ide_host *host;
unsigned long base;
- hw_regs_t hw;
- ide_hwif_t *hwif = NULL;
int i, rc;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
rc = pci_enable_device(dev);
if (rc) {
@@ -87,34 +86,26 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
hw.dev = &dev->dev;
hw.chipset = ide_pci; /* this enables IRQ sharing */
- hwif = ide_find_port();
- if (hwif == NULL)
+ rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+ if (rc)
goto out_disable;
- i = hwif->index;
-
- ide_init_port_hw(hwif, &hw);
-
- idx[0] = i;
-
- ide_device_add(idx, &delkin_cb_port_info);
-
- pci_set_drvdata(dev, hwif);
+ pci_set_drvdata(dev, host);
return 0;
out_disable:
pci_release_regions(dev);
pci_disable_device(dev);
- return -ENODEV;
+ return rc;
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
- ide_hwif_t *hwif = pci_get_drvdata(dev);
+ struct ide_host *host = pci_get_drvdata(dev);
- ide_unregister(hwif);
+ ide_host_remove(host);
pci_release_regions(dev);
pci_disable_device(dev);
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 84c36c11719..9e1d1c4741d 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -123,7 +123,6 @@ static const struct ide_port_ops hpt34x_port_ops = {
#define IDE_HFLAGS_HPT34X \
(IDE_HFLAG_NO_ATAPI_DMA | \
IDE_HFLAG_NO_DSC | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_NO_AUTODMA)
static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 397c6cbe953..1f1135ce7cd 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -801,9 +801,9 @@ static void hpt370_irq_timeout(ide_drive_t *drive)
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
/* get DMA command mode */
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~0x1, hwif->dma_command);
+ outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
hpt370_clear_engine(drive);
}
@@ -818,12 +818,12 @@ static void hpt370_dma_start(ide_drive_t *drive)
static int hpt370_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01) {
/* wait a little */
udelay(20);
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01)
hpt370_irq_timeout(drive);
}
@@ -850,7 +850,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
return 0;
}
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* return 1 if INTR asserted */
if (dma_stat & 4)
return 1;
@@ -1320,7 +1320,15 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
unsigned long flags, base = ide_pci_dma_base(hwif, d);
u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
dma_old = inb(base + 2);
@@ -1346,7 +1354,7 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
return 0;
}
@@ -1401,7 +1409,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
#define IDE_HFLAGS_HPT3XX \
(IDE_HFLAG_NO_ATAPI_DMA | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops hpt3xx_port_ops = {
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 45ba71a7182..5cd2b32ff0e 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -28,10 +28,6 @@
*/
#include <asm/superio.h>
-static unsigned long superio_ide_status[2];
-static unsigned long superio_ide_select[2];
-static unsigned long superio_ide_dma_status[2];
-
#define SUPERIO_IDE_MAX_RETRIES 25
/* Because of a defect in Super I/O, all reads of the PCI DMA status
@@ -40,27 +36,28 @@ static unsigned long superio_ide_dma_status[2];
*/
static u8 superio_ide_inb (unsigned long port)
{
- if (port == superio_ide_status[0] ||
- port == superio_ide_status[1] ||
- port == superio_ide_select[0] ||
- port == superio_ide_select[1] ||
- port == superio_ide_dma_status[0] ||
- port == superio_ide_dma_status[1]) {
- u8 tmp;
- int retries = SUPERIO_IDE_MAX_RETRIES;
+ u8 tmp;
+ int retries = SUPERIO_IDE_MAX_RETRIES;
- /* printk(" [ reading port 0x%x with retry ] ", port); */
+ /* printk(" [ reading port 0x%x with retry ] ", port); */
- do {
- tmp = inb(port);
- if (tmp == 0)
- udelay(50);
- } while (tmp == 0 && retries-- > 0);
+ do {
+ tmp = inb(port);
+ if (tmp == 0)
+ udelay(50);
+ } while (tmp == 0 && retries-- > 0);
- return tmp;
- }
+ return tmp;
+}
- return inb(port);
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->io_ports.status_addr);
+}
+
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
}
static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
@@ -78,6 +75,8 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -105,36 +104,32 @@ static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
}
}
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
-{
- struct pci_dev *pdev = to_pci_dev(hwif->dev);
- u32 base, dmabase;
- u8 port = hwif->channel, tmp;
+static const struct ide_tp_ops superio_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = superio_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = superio_read_sff_dma_status,
- base = pci_resource_start(pdev, port * 2) & ~3;
- dmabase = pci_resource_start(pdev, 4) & ~3;
-
- superio_ide_status[port] = base + 7;
- superio_ide_select[port] = base + 6;
- superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
-
- /* Clear error/interrupt, enable dma */
- tmp = superio_ide_inb(superio_ide_dma_status[port]);
- outb(tmp | 0x66, superio_ide_dma_status[port]);
+ .set_irq = ide_set_irq,
- hwif->tf_read = superio_tf_read;
+ .tf_load = ide_tf_load,
+ .tf_read = superio_tf_read,
- /* We need to override inb to workaround a SuperIO errata */
- hwif->INB = superio_ide_inb;
-}
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
+static void __devinit superio_init_iops(struct hwif_s *hwif)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ u32 dma_stat;
+ u8 port = hwif->channel, tmp;
- if (PCI_SLOT(dev->devfn) == 0xE)
- /* Built-in - assume it's under superio. */
- superio_ide_init_iops(hwif);
+ dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
+
+ /* Clear error/interrupt, enable dma */
+ tmp = superio_ide_inb(dma_stat);
+ outb(tmp | 0x66, dma_stat);
}
#endif
@@ -200,14 +195,14 @@ static int ns87415_dma_end(ide_drive_t *drive)
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- dma_stat = hwif->INB(hwif->dma_status);
- /* get dma command mode */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ /* get DMA command mode */
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
/* from ERRATA: clear the INTR & ERROR bits */
- dma_cmd = hwif->INB(hwif->dma_command);
- outb(dma_cmd | 6, hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -276,7 +271,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
outb(8, hwif->io_ports.ctl_addr);
do {
udelay(50);
- stat = hwif->INB(hwif->io_ports.status_addr);
+ stat = hwif->tp_ops->read_status(hwif);
if (stat == 0xff)
break;
} while ((stat & BUSY_STAT) && --timeout);
@@ -291,7 +286,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- outb(0x60, hwif->dma_status);
+ outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
}
static const struct ide_port_ops ns87415_port_ops = {
@@ -311,9 +306,6 @@ static const struct ide_dma_ops ns87415_dma_ops = {
static const struct ide_port_info ns87415_chipset __devinitdata = {
.name = "NS87415",
-#ifdef CONFIG_SUPERIO
- .init_iops = init_iops_ns87415,
-#endif
.init_hwif = init_hwif_ns87415,
.port_ops = &ns87415_port_ops,
.dma_ops = &ns87415_dma_ops,
@@ -323,7 +315,16 @@ static const struct ide_port_info ns87415_chipset __devinitdata = {
static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_setup_pci_device(dev, &ns87415_chipset);
+ struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+ if (PCI_SLOT(dev->devfn) == 0xE) {
+ /* Built-in - assume it's under superio. */
+ d.init_iops = superio_init_iops;
+ d.tp_ops = &superio_tp_ops;
+ }
+#endif
+ return ide_setup_pci_device(dev, &d);
}
static const struct pci_device_id ns87415_pci_tbl[] = {
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index fca89eda5c0..e54dc653b8c 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -206,7 +206,7 @@ static int pdc202xx_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->extra_base - 16;
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 sc1d = inb(high_16 + 0x001d);
if (hwif->channel) {
@@ -312,7 +312,6 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
#define IDE_HFLAGS_PDC202XX \
(IDE_HFLAG_ERROR_STOPS_FIFO | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE | \
IDE_HFLAG_OFF_BOARD)
static const struct ide_port_ops pdc20246_port_ops = {
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index f04738d14a6..0ce41b4ddda 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -227,9 +227,9 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
u8 dma_stat;
/* clear the INTR & ERROR bits */
- dma_stat = inb(hwif->dma_status);
+ dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Should we force the bit as well ? */
- outb(dma_stat, hwif->dma_status);
+ outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
}
struct ich_laptop {
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 789c66dfbde..94a7ab86423 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -65,7 +65,7 @@
static struct scc_ports {
unsigned long ctl, dma;
- ide_hwif_t *hwif; /* for removing port from system */
+ struct ide_host *host; /* for removing port from system */
} scc_ports[MAX_HWIFS];
/* PIO transfer mode table */
@@ -126,6 +126,46 @@ static u8 scc_ide_inb(unsigned long port)
return (u8)data;
}
+static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ out_be32((void *)hwif->io_ports.command_addr, cmd);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
+static u8 scc_read_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.status_addr);
+}
+
+static u8 scc_read_altstatus(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
+}
+
+static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+{
+ return (u8)in_be32((void *)(hwif->dma_base + 4));
+}
+
+static void scc_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ out_be32((void *)hwif->io_ports.ctl_addr, ctl);
+ eieio();
+ in_be32((void *)(hwif->dma_base + 0x01c));
+ eieio();
+}
+
static void scc_ide_insw(unsigned long port, void *addr, u32 count)
{
u16 *ptr = (u16 *)addr;
@@ -148,14 +188,6 @@ static void scc_ide_outb(u8 addr, unsigned long port)
out_be32((void*)port, addr);
}
-static void scc_ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
- out_be32((void*)port, addr);
- eieio();
- in_be32((void*)(hwif->dma_base + 0x01c));
- eieio();
-}
-
static void
scc_ide_outsw(unsigned long port, void *addr, u32 count)
{
@@ -261,14 +293,14 @@ static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
u8 unit = (drive->select.b.unit & 0x01);
- u8 dma_stat = scc_ide_inb(hwif->dma_status);
+ u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- scc_ide_outb(dma_stat, hwif->dma_status);
+ scc_ide_outb(dma_stat, hwif->dma_base + 4);
}
/**
@@ -304,13 +336,13 @@ static int scc_dma_setup(ide_drive_t *drive)
out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
/* specify r/w */
- out_be32((void __iomem *)hwif->dma_command, reading);
+ out_be32((void __iomem *)hwif->dma_base, reading);
- /* read dma_status for INTR & ERROR flags */
- dma_stat = in_be32((void __iomem *)hwif->dma_status);
+ /* read DMA status for INTR & ERROR flags */
+ dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
/* clear INTR & ERROR flags */
- out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+ out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
drive->waiting_for_dma = 1;
return 0;
}
@@ -318,10 +350,10 @@ static int scc_dma_setup(ide_drive_t *drive)
static void scc_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 dma_cmd = scc_ide_inb(hwif->dma_command);
+ u8 dma_cmd = scc_ide_inb(hwif->dma_base);
/* start DMA */
- scc_ide_outb(dma_cmd | 1, hwif->dma_command);
+ scc_ide_outb(dma_cmd | 1, hwif->dma_base);
hwif->dma = 1;
wmb();
}
@@ -333,13 +365,13 @@ static int __scc_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA command mode */
- dma_cmd = scc_ide_inb(hwif->dma_command);
+ dma_cmd = scc_ide_inb(hwif->dma_base);
/* stop DMA */
- scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
+ scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
/* get DMA status */
- dma_stat = scc_ide_inb(hwif->dma_status);
+ dma_stat = scc_ide_inb(hwif->dma_base + 4);
/* clear the INTR & ERROR bits */
- scc_ide_outb(dma_stat | 6, hwif->dma_status);
+ scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -359,6 +391,7 @@ static int __scc_dma_end(ide_drive_t *drive)
static int scc_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
+ void __iomem *dma_base = (void __iomem *)hwif->dma_base;
unsigned long intsts_port = hwif->dma_base + 0x014;
u32 reg;
int dma_stat, data_loss = 0;
@@ -397,7 +430,7 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -412,7 +445,7 @@ static int scc_dma_end(ide_drive_t *drive)
out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
@@ -420,12 +453,12 @@ static int scc_dma_end(ide_drive_t *drive)
printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
continue;
}
if (reg & INTSTS_ICERR) {
- out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
@@ -553,14 +586,9 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = NULL;
- hw_regs_t hw;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- int i;
-
- hwif = ide_find_port_slot(d);
- if (hwif == NULL)
- return -ENOMEM;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+ int i, rc;
memset(&hw, 0, sizeof(hw));
for (i = 0; i <= 8; i++)
@@ -568,11 +596,12 @@ static int scc_ide_setup_pci_device(struct pci_dev *dev,
hw.irq = dev->irq;
hw.dev = &dev->dev;
hw.chipset = ide_pci;
- ide_init_port_hw(hwif, &hw);
- idx[0] = hwif->index;
+ rc = ide_host_add(d, hws, &host);
+ if (rc)
+ return rc;
- ide_device_add(idx, d);
+ ports->host = host;
return 0;
}
@@ -701,6 +730,8 @@ static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
/* be sure we're looking at the low order bits */
scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = scc_ide_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = scc_ide_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -774,16 +805,6 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
ide_set_hwifdata(hwif, ports);
- hwif->tf_load = scc_tf_load;
- hwif->tf_read = scc_tf_read;
-
- hwif->input_data = scc_input_data;
- hwif->output_data = scc_output_data;
-
- hwif->INB = scc_ide_inb;
- hwif->OUTB = scc_ide_outb;
- hwif->OUTBSYNC = scc_ide_outbsync;
-
hwif->dma_base = dma_base;
hwif->config_data = ports->ctl;
}
@@ -824,11 +845,6 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
{
struct scc_ports *ports = ide_get_hwifdata(hwif);
- ports->hwif = hwif;
-
- hwif->dma_command = hwif->dma_base;
- hwif->dma_status = hwif->dma_base + 0x04;
-
/* PTERADD */
out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
@@ -838,6 +854,21 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
}
+static const struct ide_tp_ops scc_tp_ops = {
+ .exec_command = scc_exec_command,
+ .read_status = scc_read_status,
+ .read_altstatus = scc_read_altstatus,
+ .read_sff_dma_status = scc_read_sff_dma_status,
+
+ .set_irq = scc_set_irq,
+
+ .tf_load = scc_tf_load,
+ .tf_read = scc_tf_read,
+
+ .input_data = scc_input_data,
+ .output_data = scc_output_data,
+};
+
static const struct ide_port_ops scc_port_ops = {
.set_pio_mode = scc_set_pio_mode,
.set_dma_mode = scc_set_dma_mode,
@@ -861,6 +892,7 @@ static const struct ide_dma_ops scc_dma_ops = {
.name = name_str, \
.init_iops = init_iops_scc, \
.init_hwif = init_hwif_scc, \
+ .tp_ops = &scc_tp_ops, \
.port_ops = &scc_port_ops, \
.dma_ops = &scc_dma_ops, \
.host_flags = IDE_HFLAG_SINGLE, \
@@ -895,7 +927,8 @@ static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_i
static void __devexit scc_remove(struct pci_dev *dev)
{
struct scc_ports *ports = pci_get_drvdata(dev);
- ide_hwif_t *hwif = ports->hwif;
+ struct ide_host *host = ports->host;
+ ide_hwif_t *hwif = host->ports[0];
if (hwif->dmatable_cpu) {
pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
@@ -903,7 +936,7 @@ static void __devexit scc_remove(struct pci_dev *dev)
hwif->dmatable_cpu = NULL;
}
- ide_unregister(hwif);
+ ide_host_remove(host);
iounmap((void*)ports->dma);
iounmap((void*)ports->ctl);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index a1fb20826a5..127ccb45e26 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -349,9 +349,7 @@ static const struct ide_port_ops svwks_port_ops = {
.cable_detect = svwks_cable_detect,
};
-#define IDE_HFLAGS_SVWKS \
- (IDE_HFLAG_LEGACY_IRQS | \
- IDE_HFLAG_ABUSE_SET_DMA_MODE)
+#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
{ /* 0 */
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index c79ff5b4108..42eef19a18f 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -127,7 +127,7 @@ sgiioc4_checkirq(ide_hwif_t * hwif)
return 0;
}
-static u8 sgiioc4_INB(unsigned long);
+static u8 sgiioc4_read_status(ide_hwif_t *);
static int
sgiioc4_clearirq(ide_drive_t * drive)
@@ -141,18 +141,19 @@ sgiioc4_clearirq(ide_drive_t * drive)
intr_reg = readl((void __iomem *)other_ir);
if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
/*
- * Using sgiioc4_INB to read the Status register has a side
- * effect of clearing the interrupt. The first read should
+ * Using sgiioc4_read_status to read the Status register has a
+ * side effect of clearing the interrupt. The first read should
* clear it if it is set. The second read should return
* a "clear" status if it got cleared. If not, then spin
* for a bit trying to clear it.
*/
- u8 stat = sgiioc4_INB(io_ports->status_addr);
+ u8 stat = sgiioc4_read_status(hwif);
int count = 0;
- stat = sgiioc4_INB(io_ports->status_addr);
+
+ stat = sgiioc4_read_status(hwif);
while ((stat & 0x80) && (count++ < 100)) {
udelay(1);
- stat = sgiioc4_INB(io_ports->status_addr);
+ stat = sgiioc4_read_status(hwif);
}
if (intr_reg & 0x02) {
@@ -304,9 +305,9 @@ sgiioc4_dma_lost_irq(ide_drive_t * drive)
ide_dma_lost_irq(drive);
}
-static u8
-sgiioc4_INB(unsigned long port)
+static u8 sgiioc4_read_status(ide_hwif_t *hwif)
{
+ unsigned long port = hwif->io_ports.status_addr;
u8 reg = (u8) readb((void __iomem *) port);
if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
@@ -549,6 +550,21 @@ static int sgiioc4_dma_setup(ide_drive_t *drive)
return 0;
}
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = sgiioc4_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops sgiioc4_port_ops = {
.set_dma_mode = sgiioc4_set_dma_mode,
/* reset DMA engine, clear IRQs */
@@ -571,6 +587,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitdata = {
.name = DRV_NAME,
.chipset = ide_pci,
.init_dma = ide_dma_sgiioc4,
+ .tp_ops = &sgiioc4_tp_ops,
.port_ops = &sgiioc4_port_ops,
.dma_ops = &sgiioc4_dma_ops,
.host_flags = IDE_HFLAG_MMIO,
@@ -583,10 +600,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
unsigned long cmd_base, irqport;
unsigned long bar0, cmd_phys_base, ctl;
void __iomem *virt_base;
- ide_hwif_t *hwif;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- hw_regs_t hw;
+ struct ide_host *host;
+ hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
struct ide_port_info d = sgiioc4_port_info;
+ int rc;
/* Get the CmdBlk and CtrlBlk Base Registers */
bar0 = pci_resource_start(dev, 0);
@@ -618,30 +635,26 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
hw.chipset = ide_pci;
hw.dev = &dev->dev;
- hwif = ide_find_port_slot(&d);
- if (hwif == NULL)
- goto err;
-
- ide_init_port_hw(hwif, &hw);
-
- /* The IOC4 uses MMIO rather than Port IO. */
- default_hwif_mmiops(hwif);
-
/* Initializing chipset IRQ Registers */
writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
- hwif->INB = &sgiioc4_INB;
-
- idx[0] = hwif->index;
+ host = ide_host_alloc(&d, hws);
+ if (host == NULL) {
+ rc = -ENOMEM;
+ goto err;
+ }
- if (ide_device_add(idx, &d))
- return -EIO;
+ rc = ide_host_register(host, &d, hws);
+ if (rc)
+ goto err_free;
return 0;
+err_free:
+ ide_host_free(host);
err:
release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
iounmap(virt_base);
- return -ENOMEM;
+ return rc;
}
static unsigned int __devinit
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6e9d7655d89..5965a35d94a 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -334,7 +334,7 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 1);
/* return 1 if INTR asserted */
- if (hwif->INB(hwif->dma_status) & 4)
+ if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -382,7 +382,7 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
}
/* return 1 if INTR asserted */
- if (readb((void __iomem *)hwif->dma_status) & 0x04)
+ if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
return 1;
/* return 1 if Device INTR asserted */
@@ -601,7 +601,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
* Fill in the basic hwif bits
*/
hwif->host_flags |= IDE_HFLAG_MMIO;
- default_hwif_mmiops(hwif);
+
hwif->hwif_data = addr;
/*
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 6efbde29717..f82a6502c1b 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -157,9 +157,9 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
* Was DMA enabled? If so, disable it - we're resetting the
* host. The IDE layer will be handling the drive for us.
*/
- dma_cmd = inb(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
if (dma_cmd & 1) {
- outb(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
printk("sl82c105: DMA was enabled\n");
}
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 9b4b27a4c71..477e1979010 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -63,7 +63,7 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- u8 dma_stat = inb(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Restore a higher level driver's expiry handler first. */
hwgroup->expiry = expiry;
@@ -71,21 +71,24 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
- u8 dma_cmd = inb(hwif->dma_command);
+ u8 dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
"attempting recovery...\n", drive->name);
/* Stop DMA */
- outb(dma_cmd & ~0x01, hwif->dma_command);
+ outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
/* Setup the dummy DMA transfer */
outw(0, sc_base + 0x0a); /* Sector Count */
outw(0, twcr_port); /* Transfer Word Count 1 or 2 */
/* Start the dummy DMA transfer */
- outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
- outb(0x01, hwif->dma_command); /* set START_STOPBM */
+
+ /* clear R_OR_WCTR for write */
+ outb(0x00, hwif->dma_base + ATA_DMA_CMD);
+ /* set START_STOPBM */
+ outb(0x01, hwif->dma_base + ATA_DMA_CMD);
/*
* If an interrupt was pending, it should come thru shortly.
@@ -203,8 +206,7 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
.init_hwif = init_hwif_tc86c001,
.port_ops = &tc86c001_port_ops,
.dma_ops = &tc86c001_dma_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
- IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA4,
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index e47384c70c4..09dc4803ef9 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -425,7 +425,6 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
.enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
.port_ops = &via_port_ops,
.host_flags = IDE_HFLAG_PIO_NO_BLACKLIST |
- IDE_HFLAG_ABUSE_SET_DMA_MODE |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_IO_32BIT,
.pio_mask = ATA_PIO5,
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 93fb9067c04..c521bf6e1bf 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -48,6 +48,8 @@
#include <asm/mediabay.h>
#endif
+#define DRV_NAME "ide-pmac"
+
#undef IDE_PMAC_DEBUG
#define DMA_WAIT_TIMEOUT 50
@@ -424,7 +426,9 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
static void
pmac_ide_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -444,7 +448,9 @@ pmac_ide_selectproc(ide_drive_t *drive)
static void
pmac_ide_kauai_selectproc(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -465,7 +471,9 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
static void
pmac_ide_do_update_timings(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
if (pmif == NULL)
return;
@@ -478,12 +486,26 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
pmac_ide_selectproc(drive);
}
-static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
+static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
{
- u32 tmp;
-
- writeb(value, (void __iomem *) port);
- tmp = readl((void __iomem *)(hwif->io_ports.data_addr
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ + IDE_TIMING_CONFIG));
+}
+
+static void pmac_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ (void)readl((void __iomem *)(hwif->io_ports.data_addr
+ IDE_TIMING_CONFIG));
}
@@ -493,11 +515,13 @@ static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
static void
pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
u32 *timings, t;
unsigned accessTicks, recTicks;
unsigned accessTime, recTime;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
unsigned int cycle_time;
if (pmif == NULL)
@@ -778,9 +802,11 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
int unit = (drive->select.b.unit & 0x01);
int ret = 0;
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
u32 *timings, *timings2, tl[2];
timings = &pmif->timings[unit];
@@ -852,11 +878,8 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
/* Suspend call back, should be called after the child devices
* have actually been suspended
*/
-static int
-pmac_ide_do_suspend(ide_hwif_t *hwif)
+static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* We clear the timings */
pmif->timings[0] = 0;
pmif->timings[1] = 0;
@@ -884,11 +907,8 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
/* Resume call back, should be called before the child devices
* are resumed
*/
-static int
-pmac_ide_do_resume(ide_hwif_t *hwif)
+static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-
/* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
if (!pmif->mediabay) {
ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
@@ -916,7 +936,8 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)ide_get_hwifdata(hwif);
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct device_node *np = pmif->node;
const char *cable = of_get_property(np, "cable-type", NULL);
@@ -936,7 +957,40 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA40;
}
+static void pmac_ide_init_dev(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+ if (pmif->mediabay) {
+#ifdef CONFIG_PMAC_MEDIABAY
+ if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+ drive->noprobe = 0;
+ return;
+ }
+#endif
+ drive->noprobe = 1;
+ }
+}
+
+static const struct ide_tp_ops pmac_tp_ops = {
+ .exec_command = pmac_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+ .read_sff_dma_status = ide_read_sff_dma_status,
+
+ .set_irq = pmac_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
+
static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_kauai_selectproc,
@@ -944,6 +998,7 @@ static const struct ide_port_ops pmac_ide_ata6_port_ops = {
};
static const struct ide_port_ops pmac_ide_ata4_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -951,6 +1006,7 @@ static const struct ide_port_ops pmac_ide_ata4_port_ops = {
};
static const struct ide_port_ops pmac_ide_port_ops = {
+ .init_dev = pmac_ide_init_dev,
.set_pio_mode = pmac_ide_set_pio_mode,
.set_dma_mode = pmac_ide_set_dma_mode,
.selectproc = pmac_ide_selectproc,
@@ -959,12 +1015,14 @@ static const struct ide_port_ops pmac_ide_port_ops = {
static const struct ide_dma_ops pmac_dma_ops;
static const struct ide_port_info pmac_port_info = {
+ .name = DRV_NAME,
.init_dma = pmac_ide_init_dma,
.chipset = ide_pmac,
+ .tp_ops = &pmac_tp_ops,
+ .port_ops = &pmac_ide_port_ops,
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
.dma_ops = &pmac_dma_ops,
#endif
- .port_ops = &pmac_ide_port_ops,
.host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_MMIO |
@@ -977,13 +1035,15 @@ static const struct ide_port_info pmac_port_info = {
* Setup, register & probe an IDE channel driven by this driver, this is
* called by one of the 2 probe functions (macio or PCI).
*/
-static int __devinit
-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
{
struct device_node *np = pmif->node;
const int *bidp;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ struct ide_host *host;
+ ide_hwif_t *hwif;
+ hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
struct ide_port_info d = pmac_port_info;
+ int rc;
pmif->broken_dma = pmif->broken_dma_warn = 0;
if (of_device_is_compatible(np, "shasta-ata")) {
@@ -1054,31 +1114,16 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
}
- /* Setup MMIO ops */
- default_hwif_mmiops(hwif);
- hwif->OUTBSYNC = pmac_outbsync;
+ printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
+ "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+ pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+ pmif->mediabay ? " (mediabay)" : "", hw->irq);
- hwif->hwif_data = pmif;
- ide_init_port_hw(hwif, hw);
+ rc = ide_host_add(&d, hws, &host);
+ if (rc)
+ return rc;
- printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
- hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
- pmif->mediabay ? " (mediabay)" : "", hwif->irq);
-
- if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
- if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
-#else
- if (1) {
-#endif
- hwif->drives[0].noprobe = 1;
- hwif->drives[1].noprobe = 1;
- }
- }
-
- idx[0] = hwif->index;
-
- ide_device_add(idx, &d);
+ hwif = host->ports[0];
return 0;
}
@@ -1101,7 +1146,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
void __iomem *base;
unsigned long regbase;
- ide_hwif_t *hwif;
pmac_ide_hwif_t *pmif;
int irq, rc;
hw_regs_t hw;
@@ -1110,14 +1154,6 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
- printk(KERN_ERR " %s\n", mdev->ofdev.node->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (macio_resource_count(mdev) == 0) {
printk(KERN_WARNING "ide-pmac: no address for %s\n",
mdev->ofdev.node->full_name);
@@ -1164,7 +1200,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
} else
pmif->dma_regs = NULL;
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- dev_set_drvdata(&mdev->ofdev.dev, hwif);
+ dev_set_drvdata(&mdev->ofdev.dev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
@@ -1172,7 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
hw.dev = &mdev->bus->pdev->dev;
hw.parent = &mdev->ofdev.dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
dev_set_drvdata(&mdev->ofdev.dev, NULL);
@@ -1195,12 +1231,13 @@ out_free_pmif:
static int
pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
if (mesg.event != mdev->ofdev.dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = mesg;
}
@@ -1211,11 +1248,12 @@ pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
static int
pmac_ide_macio_resume(struct macio_dev *mdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+ int rc = 0;
+
if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
mdev->ofdev.dev.power.power_state = PMSG_ON;
}
@@ -1229,7 +1267,6 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
static int __devinit
pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
- ide_hwif_t *hwif;
struct device_node *np;
pmac_ide_hwif_t *pmif;
void __iomem *base;
@@ -1247,14 +1284,6 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (pmif == NULL)
return -ENOMEM;
- hwif = ide_find_port();
- if (hwif == NULL) {
- printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
- printk(KERN_ERR " %s\n", np->full_name);
- rc = -ENODEV;
- goto out_free_pmif;
- }
-
if (pci_enable_device(pdev)) {
printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
"%s\n", np->full_name);
@@ -1284,14 +1313,14 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pmif->kauai_fcr = base;
pmif->irq = pdev->irq;
- pci_set_drvdata(pdev, hwif);
+ pci_set_drvdata(pdev, pmif);
memset(&hw, 0, sizeof(hw));
pmac_ide_init_ports(&hw, pmif->regbase);
hw.irq = pdev->irq;
hw.dev = &pdev->dev;
- rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ rc = pmac_ide_setup_device(pmif, &hw);
if (rc != 0) {
/* The inteface is released to the common IDE layer */
pci_set_drvdata(pdev, NULL);
@@ -1310,12 +1339,12 @@ out_free_pmif:
static int
pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (mesg.event != pdev->dev.power.power_state.event
&& (mesg.event & PM_EVENT_SLEEP)) {
- rc = pmac_ide_do_suspend(hwif);
+ rc = pmac_ide_do_suspend(pmif);
if (rc == 0)
pdev->dev.power.power_state = mesg;
}
@@ -1326,11 +1355,11 @@ pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
static int
pmac_ide_pci_resume(struct pci_dev *pdev)
{
- ide_hwif_t *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
- int rc = 0;
-
+ pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+ int rc = 0;
+
if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
- rc = pmac_ide_do_resume(hwif);
+ rc = pmac_ide_do_resume(pmif);
if (rc == 0)
pdev->dev.power.power_state = PMSG_ON;
}
@@ -1421,10 +1450,11 @@ out:
static int
pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
{
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct dbdma_cmd *table;
int i, count = 0;
- ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
struct scatterlist *sg;
int wr = (rq_data_dir(rq) == WRITE);
@@ -1520,7 +1550,8 @@ static int
pmac_ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct request *rq = HWGROUP(drive)->rq;
u8 unit = (drive->select.b.unit & 0x01);
u8 ata4;
@@ -1560,7 +1591,9 @@ pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
static void
pmac_ide_dma_start(ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
dma = pmif->dma_regs;
@@ -1576,7 +1609,9 @@ pmac_ide_dma_start(ide_drive_t *drive)
static int
pmac_ide_dma_end (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
u32 dstat;
@@ -1604,7 +1639,9 @@ pmac_ide_dma_end (ide_drive_t *drive)
static int
pmac_ide_dma_test_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
unsigned long status, timeout;
@@ -1664,7 +1701,9 @@ static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
static void
pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
- pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+ ide_hwif_t *hwif = drive->hwif;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
volatile struct dbdma_regs __iomem *dma;
unsigned long status;
@@ -1694,7 +1733,8 @@ static const struct ide_dma_ops pmac_dma_ops = {
static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
const struct ide_port_info *d)
{
- pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+ pmac_ide_hwif_t *pmif =
+ (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
struct pci_dev *dev = to_pci_dev(hwif->dev);
/* We won't need pci_dev if we switch to generic consistent
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 65fc08b6b6d..b15cad58dc8 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -73,15 +73,12 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
* @d: IDE port info
*
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
- * Where a device has a partner that is already in DMA mode we check
- * and enforce IDE simplex rules.
*/
unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
{
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long dma_base = 0;
- u8 dma_stat = 0;
if (hwif->host_flags & IDE_HFLAG_MMIO)
return hwif->dma_base;
@@ -102,11 +99,19 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
if (hwif->channel)
dma_base += 8;
- if (d->host_flags & IDE_HFLAG_CS5520)
+ return dma_base;
+}
+EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+
+int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+ u8 dma_stat;
+
+ if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
goto out;
if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
- ide_pci_clear_simplex(dma_base, d->name);
+ ide_pci_clear_simplex(hwif->dma_base, d->name);
goto out;
}
@@ -120,15 +125,15 @@ unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
* we tune the drive then try to grab DMA ownership if we want to be
* the DMA end. This has to be become dynamic to handle hot-plug.
*/
- dma_stat = hwif->INB(dma_base + 2);
+ dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
- dma_base = 0;
+ return -1;
}
out:
- return dma_base;
+ return 0;
}
-EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+EXPORT_SYMBOL_GPL(ide_pci_check_simplex);
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
@@ -284,33 +289,31 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
}
/**
- * ide_hwif_configure - configure an IDE interface
+ * ide_hw_configure - configure a hw_regs_t instance
* @dev: PCI device holding interface
* @d: IDE port info
* @port: port number
* @irq: PCI IRQ
+ * @hw: hw_regs_t instance corresponding to this port
*
* Perform the initial set up for the hardware interface structure. This
* is done per interface port rather than per PCI device. There may be
* more than one port per device.
*
- * Returns the new hardware interface structure, or NULL on a failure
+ * Returns zero on success or an error code.
*/
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
- const struct ide_port_info *d,
- unsigned int port, int irq)
+static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
+ unsigned int port, int irq, hw_regs_t *hw)
{
unsigned long ctl = 0, base = 0;
- ide_hwif_t *hwif;
- struct hw_regs_s hw;
if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
if (ide_pci_check_iomem(dev, d, 2 * port) ||
ide_pci_check_iomem(dev, d, 2 * port + 1)) {
printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
"as MEM for port %d!\n", d->name, port);
- return NULL;
+ return -EINVAL;
}
ctl = pci_resource_start(dev, 2*port+1);
@@ -324,22 +327,16 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
if (!base || !ctl) {
printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n",
d->name, port);
- return NULL;
+ return -EINVAL;
}
- hwif = ide_find_port_slot(d);
- if (hwif == NULL)
- return NULL;
-
- memset(&hw, 0, sizeof(hw));
- hw.irq = irq;
- hw.dev = &dev->dev;
- hw.chipset = d->chipset ? d->chipset : ide_pci;
- ide_std_init_ports(&hw, base, ctl | 2);
-
- ide_init_port_hw(hwif, &hw);
+ memset(hw, 0, sizeof(*hw));
+ hw->irq = irq;
+ hw->dev = &dev->dev;
+ hw->chipset = d->chipset ? d->chipset : ide_pci;
+ ide_std_init_ports(hw, base, ctl | 2);
- return hwif;
+ return 0;
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -362,7 +359,15 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
(dev->class & 0x80))) {
unsigned long base = ide_pci_dma_base(hwif, d);
- if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+ if (base == 0)
+ return -1;
+
+ hwif->dma_base = base;
+
+ if (ide_pci_check_simplex(hwif, d) < 0)
+ return -1;
+
+ if (ide_pci_set_master(dev, d->name) < 0)
return -1;
if (hwif->host_flags & IDE_HFLAG_MMIO)
@@ -376,7 +381,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
if (ide_allocate_dma_engine(hwif))
return -1;
- ide_setup_dma(hwif, base);
+ hwif->dma_ops = &sff_dma_ops;
}
return 0;
@@ -429,7 +434,8 @@ out:
* @dev: PCI device
* @d: IDE port info
* @pciirq: IRQ line
- * @idx: ATA index table to update
+ * @hw: hw_regs_t instances corresponding to this PCI IDE device
+ * @hws: hw_regs_t pointers table to update
*
* Scan the interfaces attached to this device and do any
* necessary per port setup. Attach the devices and ask the
@@ -440,10 +446,10 @@ out:
* where the chipset setup is not the default PCI IDE one.
*/
-void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
+void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
+ int pciirq, hw_regs_t *hw, hw_regs_t **hws)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
- ide_hwif_t *hwif;
u8 tmp;
/*
@@ -459,11 +465,10 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
continue; /* port not enabled */
}
- hwif = ide_hwif_configure(dev, d, port, pciirq);
- if (hwif == NULL)
+ if (ide_hw_configure(dev, d, port, pciirq, hw + port))
continue;
- *(idx + port) = hwif->index;
+ *(hws + port) = hw + port;
}
}
EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
@@ -480,7 +485,7 @@ EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
*/
static int do_ide_setup_pci_device(struct pci_dev *dev,
const struct ide_port_info *d,
- u8 *idx, u8 noisy)
+ u8 noisy)
{
int tried_config = 0;
int pciirq, ret;
@@ -529,22 +534,24 @@ static int do_ide_setup_pci_device(struct pci_dev *dev,
d->name, pciirq);
}
- /* FIXME: silent failure can happen */
-
- ide_pci_setup_ports(dev, d, pciirq, idx);
+ ret = pciirq;
out:
return ret;
}
int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
{
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
int ret;
- ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
+ ret = do_ide_setup_pci_device(dev, d, 1);
+
+ if (ret >= 0) {
+ /* FIXME: silent failure can happen */
+ ide_pci_setup_ports(dev, d, ret, &hw[0], &hws[0]);
- if (ret >= 0)
- ide_device_add(idx, d);
+ ret = ide_host_add(d, hws, NULL);
+ }
return ret;
}
@@ -555,19 +562,23 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
{
struct pci_dev *pdev[] = { dev1, dev2 };
int ret, i;
- u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
for (i = 0; i < 2; i++) {
- ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i);
+ ret = do_ide_setup_pci_device(pdev[i], d, !i);
+
/*
* FIXME: Mom, mom, they stole me the helper function to undo
* do_ide_setup_pci_device() on the first device!
*/
if (ret < 0)
goto out;
+
+ /* FIXME: silent failure can happen */
+ ide_pci_setup_ports(pdev[i], d, ret, &hw[i*2], &hws[i*2]);
}
- ide_device_add(idx, d);
+ ret = ide_host_add(d, hws, NULL);
out:
return ret;
}
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 9d19aec5820..b6eb2cf2591 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2296,9 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
- "dv1394-%d", id);
+ device_create_drvdata(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
+ "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 07ca35c98f9..1cf6487b65b 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include "hosts.h"
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 05710c7c122..994a21e5a0a 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -754,7 +754,8 @@ static void nodemgr_remove_uds(struct node_entry *ne)
*/
mutex_lock(&nodemgr_serialize_remove_uds);
for (;;) {
- dev = class_find_device(&nodemgr_ud_class, ne, __match_ne);
+ dev = class_find_device(&nodemgr_ud_class, NULL, ne,
+ __match_ne);
if (!dev)
break;
ud = container_of(dev, struct unit_directory, unit_dev);
@@ -901,7 +902,8 @@ static struct node_entry *find_entry_by_guid(u64 guid)
struct device *dev;
struct node_entry *ne;
- dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
+ __match_ne_guid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -940,7 +942,8 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
param.host = host;
param.nodeid = nodeid;
- dev = class_find_device(&nodemgr_ne_class, &param, __match_ne_nodeid);
+ dev = class_find_device(&nodemgr_ne_class, NULL, &param,
+ __match_ne_nodeid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
@@ -1453,7 +1456,8 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
ne->in_limbo = 1;
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_driver_suspend);
}
@@ -1462,7 +1466,8 @@ static void nodemgr_resume_ne(struct node_entry *ne)
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_driver_resume);
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
}
@@ -1498,7 +1503,8 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
- class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv);
+ class_for_each_device(&nodemgr_ud_class, NULL, ne,
+ __nodemgr_update_pdrv);
}
@@ -1591,7 +1597,8 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* while probes are time-consuming. (Well, those probes need some
* improvement...) */
- class_for_each_device(&nodemgr_ne_class, &param, __nodemgr_node_probe);
+ class_for_each_device(&nodemgr_ne_class, NULL, &param,
+ __nodemgr_node_probe);
/* If we had a bus reset while we were scanning the bus, it is
* possible that we did not probe all nodes. In that case, we
@@ -1826,7 +1833,7 @@ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
hip.cb = cb;
hip.data = data;
- error = class_for_each_device(&hpsb_host_class, &hip,
+ error = class_for_each_device(&hpsb_host_class, NULL, &hip,
__nodemgr_for_each_host);
return error;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 96f2847b040..6fa9e4a2184 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -3010,10 +3010,10 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (device_create(
+ (device_create_drvdata(
hpsb_protocol_class, NULL,
MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- RAW1394_DEVICE_NAME))) {
+ NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 069b9f6bf16..25db6e67fa4 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1341,9 +1341,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- device_create(hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, minor),
- "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create_drvdata(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, minor), NULL,
+ "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 55738eead3b..922d35f4fc0 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -44,6 +44,7 @@
#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
+#include <linux/kdev_t.h>
#include <rdma/ib_cache.h>
#include <rdma/ib_cm.h>
@@ -162,8 +163,8 @@ struct cm_port {
struct cm_device {
struct list_head list;
- struct ib_device *device;
- struct kobject dev_obj;
+ struct ib_device *ib_device;
+ struct device *device;
u8 ack_delay;
struct cm_port *port[0];
};
@@ -339,7 +340,7 @@ static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
{
av->port = port;
av->pkey_index = wc->pkey_index;
- ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc,
+ ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc,
grh, &av->ah_attr);
}
@@ -353,7 +354,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
read_lock_irqsave(&cm.device_lock, flags);
list_for_each_entry(cm_dev, &cm.device_list, list) {
- if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
+ if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
&p, NULL)) {
port = cm_dev->port[p-1];
break;
@@ -364,13 +365,13 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
if (!port)
return -EINVAL;
- ret = ib_find_cached_pkey(cm_dev->device, port->port_num,
+ ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num,
be16_to_cpu(path->pkey), &av->pkey_index);
if (ret)
return ret;
av->port = port;
- ib_init_ah_from_path(cm_dev->device, port->port_num, path,
+ ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
&av->ah_attr);
av->timeout = path->packet_life_time + 1;
return 0;
@@ -1515,7 +1516,7 @@ static int cm_req_handler(struct cm_work *work)
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
@@ -1550,7 +1551,7 @@ static int cm_req_handler(struct cm_work *work)
cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
if (ret) {
- ib_get_cached_gid(work->port->cm_dev->device,
+ ib_get_cached_gid(work->port->cm_dev->ib_device,
work->port->port_num, 0, &work->path[0].sgid);
ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
&work->path[0].sgid, sizeof work->path[0].sgid,
@@ -2950,7 +2951,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
struct cm_sidr_req_msg *sidr_req_msg;
struct ib_wc *wc;
- cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+ cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
if (IS_ERR(cm_id))
return PTR_ERR(cm_id);
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -3578,7 +3579,7 @@ static void cm_get_ack_delay(struct cm_device *cm_dev)
{
struct ib_device_attr attr;
- if (ib_query_device(cm_dev->device, &attr))
+ if (ib_query_device(cm_dev->ib_device, &attr))
cm_dev->ack_delay = 0; /* acks will rely on packet life time */
else
cm_dev->ack_delay = attr.local_ca_ack_delay;
@@ -3618,18 +3619,6 @@ static struct kobj_type cm_port_obj_type = {
.release = cm_release_port_obj
};
-static void cm_release_dev_obj(struct kobject *obj)
-{
- struct cm_device *cm_dev;
-
- cm_dev = container_of(obj, struct cm_device, dev_obj);
- kfree(cm_dev);
-}
-
-static struct kobj_type cm_dev_obj_type = {
- .release = cm_release_dev_obj
-};
-
struct class cm_class = {
.name = "infiniband_cm",
};
@@ -3640,7 +3629,7 @@ static int cm_create_port_fs(struct cm_port *port)
int i, ret;
ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
- &port->cm_dev->dev_obj,
+ &port->cm_dev->device->kobj,
"%d", port->port_num);
if (ret) {
kfree(port);
@@ -3676,7 +3665,7 @@ static void cm_remove_port_fs(struct cm_port *port)
kobject_put(&port->port_obj);
}
-static void cm_add_one(struct ib_device *device)
+static void cm_add_one(struct ib_device *ib_device)
{
struct cm_device *cm_dev;
struct cm_port *port;
@@ -3691,26 +3680,27 @@ static void cm_add_one(struct ib_device *device)
int ret;
u8 i;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
return;
cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
- device->phys_port_cnt, GFP_KERNEL);
+ ib_device->phys_port_cnt, GFP_KERNEL);
if (!cm_dev)
return;
- cm_dev->device = device;
+ cm_dev->ib_device = ib_device;
cm_get_ack_delay(cm_dev);
- ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
- &cm_class.subsys.kobj, "%s", device->name);
- if (ret) {
+ cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
+ MKDEV(0, 0), NULL,
+ "%s", ib_device->name);
+ if (!cm_dev->device) {
kfree(cm_dev);
return;
}
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
- for (i = 1; i <= device->phys_port_cnt; i++) {
+ for (i = 1; i <= ib_device->phys_port_cnt; i++) {
port = kzalloc(sizeof *port, GFP_KERNEL);
if (!port)
goto error1;
@@ -3723,7 +3713,7 @@ static void cm_add_one(struct ib_device *device)
if (ret)
goto error1;
- port->mad_agent = ib_register_mad_agent(device, i,
+ port->mad_agent = ib_register_mad_agent(ib_device, i,
IB_QPT_GSI,
&reg_req,
0,
@@ -3733,11 +3723,11 @@ static void cm_add_one(struct ib_device *device)
if (IS_ERR(port->mad_agent))
goto error2;
- ret = ib_modify_port(device, i, 0, &port_modify);
+ ret = ib_modify_port(ib_device, i, 0, &port_modify);
if (ret)
goto error3;
}
- ib_set_client_data(device, &cm_client, cm_dev);
+ ib_set_client_data(ib_device, &cm_client, cm_dev);
write_lock_irqsave(&cm.device_lock, flags);
list_add_tail(&cm_dev->list, &cm.device_list);
@@ -3753,14 +3743,14 @@ error1:
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
port = cm_dev->port[i-1];
- ib_modify_port(device, port->port_num, 0, &port_modify);
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
cm_remove_port_fs(port);
}
- kobject_put(&cm_dev->dev_obj);
+ device_unregister(cm_dev->device);
}
-static void cm_remove_one(struct ib_device *device)
+static void cm_remove_one(struct ib_device *ib_device)
{
struct cm_device *cm_dev;
struct cm_port *port;
@@ -3770,7 +3760,7 @@ static void cm_remove_one(struct ib_device *device)
unsigned long flags;
int i;
- cm_dev = ib_get_client_data(device, &cm_client);
+ cm_dev = ib_get_client_data(ib_device, &cm_client);
if (!cm_dev)
return;
@@ -3778,14 +3768,14 @@ static void cm_remove_one(struct ib_device *device)
list_del(&cm_dev->list);
write_unlock_irqrestore(&cm.device_lock, flags);
- for (i = 1; i <= device->phys_port_cnt; i++) {
+ for (i = 1; i <= ib_device->phys_port_cnt; i++) {
port = cm_dev->port[i-1];
- ib_modify_port(device, port->port_num, 0, &port_modify);
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
flush_workqueue(cm.wq);
cm_remove_port_fs(port);
}
- kobject_put(&cm_dev->dev_obj);
+ device_unregister(cm_dev->device);
}
static int __init ib_cm_init(void)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index ae11d5cc74d..e980ff3335d 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -168,6 +168,12 @@ struct cma_work {
struct rdma_cm_event event;
};
+struct cma_ndev_work {
+ struct work_struct work;
+ struct rdma_id_private *id;
+ struct rdma_cm_event event;
+};
+
union cma_ip_addr {
struct in6_addr ip6;
struct {
@@ -914,7 +920,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
struct rdma_cm_event event;
int ret = 0;
- if (cma_disable_callback(id_priv, CMA_CONNECT))
+ if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
+ cma_disable_callback(id_priv, CMA_CONNECT)) ||
+ (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
+ cma_disable_callback(id_priv, CMA_DISCONNECT)))
return 0;
memset(&event, 0, sizeof event);
@@ -950,6 +959,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
event.event = RDMA_CM_EVENT_DISCONNECTED;
break;
case IB_CM_TIMEWAIT_EXIT:
+ event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT;
+ break;
case IB_CM_MRA_RECEIVED:
/* ignore event */
goto out;
@@ -1598,6 +1609,30 @@ out:
kfree(work);
}
+static void cma_ndev_work_handler(struct work_struct *_work)
+{
+ struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
+ struct rdma_id_private *id_priv = work->id;
+ int destroy = 0;
+
+ mutex_lock(&id_priv->handler_mutex);
+ if (id_priv->state == CMA_DESTROYING ||
+ id_priv->state == CMA_DEVICE_REMOVAL)
+ goto out;
+
+ if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+ cma_exch(id_priv, CMA_DESTROYING);
+ destroy = 1;
+ }
+
+out:
+ mutex_unlock(&id_priv->handler_mutex);
+ cma_deref_id(id_priv);
+ if (destroy)
+ rdma_destroy_id(&id_priv->id);
+ kfree(work);
+}
+
static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
{
struct rdma_route *route = &id_priv->id.route;
@@ -2723,6 +2758,65 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
}
EXPORT_SYMBOL(rdma_leave_multicast);
+static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
+{
+ struct rdma_dev_addr *dev_addr;
+ struct cma_ndev_work *work;
+
+ dev_addr = &id_priv->id.route.addr.dev_addr;
+
+ if ((dev_addr->src_dev == ndev) &&
+ memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
+ printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
+ ndev->name, &id_priv->id);
+ work = kzalloc(sizeof *work, GFP_KERNEL);
+ if (!work)
+ return -ENOMEM;
+
+ INIT_WORK(&work->work, cma_ndev_work_handler);
+ work->id = id_priv;
+ work->event.event = RDMA_CM_EVENT_ADDR_CHANGE;
+ atomic_inc(&id_priv->refcount);
+ queue_work(cma_wq, &work->work);
+ }
+
+ return 0;
+}
+
+static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
+ void *ctx)
+{
+ struct net_device *ndev = (struct net_device *)ctx;
+ struct cma_device *cma_dev;
+ struct rdma_id_private *id_priv;
+ int ret = NOTIFY_DONE;
+
+ if (dev_net(ndev) != &init_net)
+ return NOTIFY_DONE;
+
+ if (event != NETDEV_BONDING_FAILOVER)
+ return NOTIFY_DONE;
+
+ if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
+ return NOTIFY_DONE;
+
+ mutex_lock(&lock);
+ list_for_each_entry(cma_dev, &dev_list, list)
+ list_for_each_entry(id_priv, &cma_dev->id_list, list) {
+ ret = cma_netdev_change(ndev, id_priv);
+ if (ret)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&lock);
+ return ret;
+}
+
+static struct notifier_block cma_nb = {
+ .notifier_call = cma_netdev_callback
+};
+
static void cma_add_one(struct ib_device *device)
{
struct cma_device *cma_dev;
@@ -2831,6 +2925,7 @@ static int cma_init(void)
ib_sa_register_client(&sa_client);
rdma_addr_register_client(&addr_client);
+ register_netdevice_notifier(&cma_nb);
ret = ib_register_client(&cma_client);
if (ret)
@@ -2838,6 +2933,7 @@ static int cma_init(void)
return 0;
err:
+ unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
destroy_workqueue(cma_wq);
@@ -2847,6 +2943,7 @@ err:
static void cma_cleanup(void)
{
ib_unregister_client(&cma_client);
+ unregister_netdevice_notifier(&cma_nb);
rdma_addr_unregister_client(&addr_client);
ib_sa_unregister_client(&sa_client);
destroy_workqueue(cma_wq);
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 81c9195b512..8f9509e1ebf 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -942,8 +942,7 @@ static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv,
case IW_CM_STATE_CONN_RECV:
case IW_CM_STATE_ESTABLISHED:
*qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE|
+ qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE|
IB_ACCESS_REMOTE_READ;
ret = 0;
break;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 1341de793e5..7863a50d56f 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1064,7 +1064,8 @@ static void ib_sa_remove_one(struct ib_device *device)
for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
ib_unregister_mad_agent(sa_dev->port[i].agent);
- kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+ if (sa_dev->port[i].sm_ah)
+ kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
}
kfree(sa_dev);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1e9e99a1393..0b0618edd64 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -194,6 +194,7 @@ struct ehca_qp {
u32 packet_count;
atomic_t nr_events; /* events seen */
wait_queue_head_t wait_completion;
+ int mig_armed;
};
#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index bc3b37d2070..46288220cfb 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -114,7 +114,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
}
props->max_pkeys = 16;
- props->local_ca_ack_delay = min_t(u8, rblock->local_ca_ack_delay, 255);
+ /* Some FW versions say 0 here; insert sensible value in that case */
+ props->local_ca_ack_delay = rblock->local_ca_ack_delay ?
+ min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp);
props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp);
props->max_mcast_grp = limit_uint(rblock->max_mcast_grp);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 0792d930c48..cb55be04442 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -178,6 +178,10 @@ static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
{
struct ib_event event;
+ /* PATH_MIG without the QP ever having been armed is false alarm */
+ if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+ return;
+
event.device = &shca->ib_device;
event.event = event_type;
@@ -646,8 +650,8 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
spin_lock_irqsave(&pool->last_cpu_lock, flags);
- cpu = next_cpu(pool->last_cpu, cpu_online_map);
- if (cpu == NR_CPUS)
+ cpu = next_cpu_nr(pool->last_cpu, cpu_online_map);
+ if (cpu >= nr_cpu_ids)
cpu = first_cpu(cpu_online_map);
pool->last_cpu = cpu;
spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 3f59587338e..ea13efddf17 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1460,6 +1460,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
goto modify_qp_exit2;
}
mqpcb->path_migration_state = attr->path_mig_state + 1;
+ if (attr->path_mig_state == IB_MIG_REARM)
+ my_qp->mig_armed = 1;
update_mask |=
EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
}
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index 661f8db6270..c3a32846543 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -163,6 +163,7 @@ static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
out:
ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
+ mutex_unlock(&pd->lock);
return 0;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 35f301c88b5..56c0eda3c07 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
goto err_cdev;
}
- device = device_create(ipath_class, NULL, dev, name);
+ device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
if (IS_ERR(device)) {
ret = PTR_ERR(device);
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 299f20832ab..0b191a4842c 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -637,6 +637,7 @@ repoll:
case MLX4_OPCODE_SEND_IMM:
wc->wc_flags |= IB_WC_WITH_IMM;
case MLX4_OPCODE_SEND:
+ case MLX4_OPCODE_SEND_INVAL:
wc->opcode = IB_WC_SEND;
break;
case MLX4_OPCODE_RDMA_READ:
@@ -657,6 +658,12 @@ repoll:
case MLX4_OPCODE_LSO:
wc->opcode = IB_WC_LSO;
break;
+ case MLX4_OPCODE_FMR:
+ wc->opcode = IB_WC_FAST_REG_MR;
+ break;
+ case MLX4_OPCODE_LOCAL_INVAL:
+ wc->opcode = IB_WC_LOCAL_INV;
+ break;
}
} else {
wc->byte_len = be32_to_cpu(cqe->byte_cnt);
@@ -667,6 +674,11 @@ repoll:
wc->wc_flags = IB_WC_WITH_IMM;
wc->ex.imm_data = cqe->immed_rss_invalid;
break;
+ case MLX4_RECV_OPCODE_SEND_INVAL:
+ wc->opcode = IB_WC_RECV;
+ wc->wc_flags = IB_WC_WITH_INVALIDATE;
+ wc->ex.invalidate_rkey = be32_to_cpu(cqe->immed_rss_invalid);
+ break;
case MLX4_RECV_OPCODE_SEND:
wc->opcode = IB_WC_RECV;
wc->wc_flags = 0;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index bcf50648fa1..38d6907ab52 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -104,6 +104,12 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
if (dev->dev->caps.max_gso_sz)
props->device_cap_flags |= IB_DEVICE_UD_TSO;
+ if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
+ props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
+ if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) &&
+ (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
+ (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
+ props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff;
@@ -127,6 +133,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1;
props->max_srq_sge = dev->dev->caps.max_srq_sge;
+ props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay;
props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -565,6 +572,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
ibdev->ib_dev.owner = THIS_MODULE;
ibdev->ib_dev.node_type = RDMA_NODE_IB_CA;
+ ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey;
ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports;
ibdev->ib_dev.num_comp_vectors = 1;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
@@ -627,6 +635,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr;
ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr;
ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr;
+ ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
+ ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
+ ibdev->ib_dev.free_fast_reg_page_list = mlx4_ib_free_fast_reg_page_list;
ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach;
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index c4cf5b69eef..d26a91317d4 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -83,6 +83,11 @@ struct mlx4_ib_mr {
struct ib_umem *umem;
};
+struct mlx4_ib_fast_reg_page_list {
+ struct ib_fast_reg_page_list ibfrpl;
+ dma_addr_t map;
+};
+
struct mlx4_ib_fmr {
struct ib_fmr ibfmr;
struct mlx4_fmr mfmr;
@@ -199,6 +204,11 @@ static inline struct mlx4_ib_mr *to_mmr(struct ib_mr *ibmr)
return container_of(ibmr, struct mlx4_ib_mr, ibmr);
}
+static inline struct mlx4_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl)
+{
+ return container_of(ibfrpl, struct mlx4_ib_fast_reg_page_list, ibfrpl);
+}
+
static inline struct mlx4_ib_fmr *to_mfmr(struct ib_fmr *ibfmr)
{
return container_of(ibfmr, struct mlx4_ib_fmr, ibfmr);
@@ -239,6 +249,11 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int access_flags,
struct ib_udata *udata);
int mlx4_ib_dereg_mr(struct ib_mr *mr);
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+ int max_page_list_len);
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+ int page_list_len);
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list);
int mlx4_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 68e92485fc7..db2086faa4e 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -183,6 +183,76 @@ int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
return 0;
}
+struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd,
+ int max_page_list_len)
+{
+ struct mlx4_ib_dev *dev = to_mdev(pd->device);
+ struct mlx4_ib_mr *mr;
+ int err;
+
+ mr = kmalloc(sizeof *mr, GFP_KERNEL);
+ if (!mr)
+ return ERR_PTR(-ENOMEM);
+
+ err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, 0, 0, 0,
+ max_page_list_len, 0, &mr->mmr);
+ if (err)
+ goto err_free;
+
+ err = mlx4_mr_enable(dev->dev, &mr->mmr);
+ if (err)
+ goto err_mr;
+
+ return &mr->ibmr;
+
+err_mr:
+ mlx4_mr_free(dev->dev, &mr->mmr);
+
+err_free:
+ kfree(mr);
+ return ERR_PTR(err);
+}
+
+struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device *ibdev,
+ int page_list_len)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ struct mlx4_ib_fast_reg_page_list *mfrpl;
+ int size = page_list_len * sizeof (u64);
+
+ if (size > PAGE_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
+ if (!mfrpl)
+ return ERR_PTR(-ENOMEM);
+
+ mfrpl->ibfrpl.page_list = dma_alloc_coherent(&dev->dev->pdev->dev,
+ size, &mfrpl->map,
+ GFP_KERNEL);
+ if (!mfrpl->ibfrpl.page_list)
+ goto err_free;
+
+ WARN_ON(mfrpl->map & 0x3f);
+
+ return &mfrpl->ibfrpl;
+
+err_free:
+ kfree(mfrpl);
+ return ERR_PTR(-ENOMEM);
+}
+
+void mlx4_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
+{
+ struct mlx4_ib_dev *dev = to_mdev(page_list->device);
+ struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list);
+ int size = page_list->max_page_list_len * sizeof (u64);
+
+ dma_free_coherent(&dev->dev->pdev->dev, size, page_list->page_list,
+ mfrpl->map);
+ kfree(mfrpl);
+}
+
struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc,
struct ib_fmr_attr *fmr_attr)
{
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 89eb6cbe592..02a99bc4442 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -78,6 +78,9 @@ static const __be32 mlx4_ib_opcode[] = {
[IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ),
[IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS),
[IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA),
+ [IB_WR_SEND_WITH_INV] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_INVAL),
+ [IB_WR_LOCAL_INV] = __constant_cpu_to_be32(MLX4_OPCODE_LOCAL_INVAL),
+ [IB_WR_FAST_REG_MR] = __constant_cpu_to_be32(MLX4_OPCODE_FMR),
};
static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp)
@@ -976,6 +979,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+ /* Set "fast registration enabled" for all kernel QPs */
+ if (!qp->ibqp.uobject)
+ context->params1 |= cpu_to_be32(1 << 11);
+
if (attr_mask & IB_QP_RNR_RETRY) {
context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
@@ -1322,6 +1329,38 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
return cur + nreq >= wq->max_post;
}
+static __be32 convert_access(int acc)
+{
+ return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC) : 0) |
+ (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) |
+ (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ) : 0) |
+ (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) |
+ cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
+}
+
+static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
+{
+ struct mlx4_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list);
+
+ fseg->flags = convert_access(wr->wr.fast_reg.access_flags);
+ fseg->mem_key = cpu_to_be32(wr->wr.fast_reg.rkey);
+ fseg->buf_list = cpu_to_be64(mfrpl->map);
+ fseg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start);
+ fseg->reg_len = cpu_to_be64(wr->wr.fast_reg.length);
+ fseg->offset = 0; /* XXX -- is this just for ZBVA? */
+ fseg->page_size = cpu_to_be32(wr->wr.fast_reg.page_shift);
+ fseg->reserved[0] = 0;
+ fseg->reserved[1] = 0;
+}
+
+static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
+{
+ iseg->flags = 0;
+ iseg->mem_key = cpu_to_be32(rkey);
+ iseg->guest_id = 0;
+ iseg->pa = 0;
+}
+
static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,
u64 remote_addr, u32 rkey)
{
@@ -1395,7 +1434,7 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
dseg->addr = cpu_to_be64(sg->addr);
}
-static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
+static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
{
unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
@@ -1423,6 +1462,21 @@ static int build_lso_seg(struct mlx4_lso_seg *wqe, struct ib_send_wr *wr,
return 0;
}
+static __be32 send_ieth(struct ib_send_wr *wr)
+{
+ switch (wr->opcode) {
+ case IB_WR_SEND_WITH_IMM:
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ return wr->ex.imm_data;
+
+ case IB_WR_SEND_WITH_INV:
+ return cpu_to_be32(wr->ex.invalidate_rkey);
+
+ default:
+ return 0;
+ }
+}
+
int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
struct ib_send_wr **bad_wr)
{
@@ -1469,11 +1523,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
MLX4_WQE_CTRL_TCP_UDP_CSUM) : 0) |
qp->sq_signal_bits;
- if (wr->opcode == IB_WR_SEND_WITH_IMM ||
- wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
- ctrl->imm = wr->ex.imm_data;
- else
- ctrl->imm = 0;
+ ctrl->imm = send_ieth(wr);
wqe += sizeof *ctrl;
size = sizeof *ctrl / 16;
@@ -1505,6 +1555,18 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
size += sizeof (struct mlx4_wqe_raddr_seg) / 16;
break;
+ case IB_WR_LOCAL_INV:
+ set_local_inv_seg(wqe, wr->ex.invalidate_rkey);
+ wqe += sizeof (struct mlx4_wqe_local_inval_seg);
+ size += sizeof (struct mlx4_wqe_local_inval_seg) / 16;
+ break;
+
+ case IB_WR_FAST_REG_MR:
+ set_fmr_seg(wqe, wr);
+ wqe += sizeof (struct mlx4_wqe_fmr_seg);
+ size += sizeof (struct mlx4_wqe_fmr_seg) / 16;
+ break;
+
default:
/* No extra segments required for sends */
break;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ee4d073c889..252590116df 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -202,6 +202,7 @@ struct mthca_pd_table {
struct mthca_buddy {
unsigned long **bits;
+ int *num_free;
int max_order;
spinlock_t lock;
};
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 8489b1e81c0..882e6b73591 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -89,23 +89,26 @@ static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
spin_lock(&buddy->lock);
- for (o = order; o <= buddy->max_order; ++o) {
- m = 1 << (buddy->max_order - o);
- seg = find_first_bit(buddy->bits[o], m);
- if (seg < m)
- goto found;
- }
+ for (o = order; o <= buddy->max_order; ++o)
+ if (buddy->num_free[o]) {
+ m = 1 << (buddy->max_order - o);
+ seg = find_first_bit(buddy->bits[o], m);
+ if (seg < m)
+ goto found;
+ }
spin_unlock(&buddy->lock);
return -1;
found:
clear_bit(seg, buddy->bits[o]);
+ --buddy->num_free[o];
while (o > order) {
--o;
seg <<= 1;
set_bit(seg ^ 1, buddy->bits[o]);
+ ++buddy->num_free[o];
}
spin_unlock(&buddy->lock);
@@ -123,11 +126,13 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
while (test_bit(seg ^ 1, buddy->bits[order])) {
clear_bit(seg ^ 1, buddy->bits[order]);
+ --buddy->num_free[order];
seg >>= 1;
++order;
}
set_bit(seg, buddy->bits[order]);
+ ++buddy->num_free[order];
spin_unlock(&buddy->lock);
}
@@ -141,7 +146,9 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- if (!buddy->bits)
+ buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ GFP_KERNEL);
+ if (!buddy->bits || !buddy->num_free)
goto err_out;
for (i = 0; i <= buddy->max_order; ++i) {
@@ -154,6 +161,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
}
set_bit(0, buddy->bits[buddy->max_order]);
+ buddy->num_free[buddy->max_order] = 1;
return 0;
@@ -161,9 +169,10 @@ err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
kfree(buddy->bits[i]);
+err_out:
kfree(buddy->bits);
+ kfree(buddy->num_free);
-err_out:
return -ENOMEM;
}
@@ -175,6 +184,7 @@ static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
kfree(buddy->bits[i]);
kfree(buddy->bits);
+ kfree(buddy->num_free);
}
static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 8be9ea0436e..f51201b17bf 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -548,7 +548,7 @@ static int path_rec_start(struct net_device *dev,
path_rec_completion,
path, &path->query);
if (path->query_id < 0) {
- ipoib_warn(priv, "ib_sa_path_rec_get failed\n");
+ ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id);
path->query = NULL;
return path->query_id;
}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 3a917c1f796..63462ecca14 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -483,6 +483,7 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
break;
case RDMA_CM_EVENT_DISCONNECTED:
case RDMA_CM_EVENT_DEVICE_REMOVAL:
+ case RDMA_CM_EVENT_ADDR_CHANGE:
iser_disconnected_handler(cma_id);
break;
default:
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index c21f2f12723..0353601ac3b 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -1,6 +1,4 @@
/*
- * $Id: evbug.c,v 1.10 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
@@ -41,7 +39,7 @@ MODULE_LICENSE("GPL");
static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
- handle->dev->phys, type, code, value);
+ handle->dev->dev.bus_id, type, code, value);
}
static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
@@ -66,7 +64,10 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
if (error)
goto err_unregister_handle;
- printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
+ printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
+ dev->dev.bus_id,
+ dev->name ?: "unknown",
+ dev->phys ?: "unknown");
return 0;
@@ -79,7 +80,8 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
static void evbug_disconnect(struct input_handle *handle)
{
- printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
+ printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
+ handle->dev->dev.bus_id);
input_close_device(handle);
input_unregister_handle(handle);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b32984bc516..2d65411f676 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -300,6 +300,35 @@ struct input_event_compat {
__s32 value;
};
+struct ff_periodic_effect_compat {
+ __u16 waveform;
+ __u16 period;
+ __s16 magnitude;
+ __s16 offset;
+ __u16 phase;
+
+ struct ff_envelope envelope;
+
+ __u32 custom_len;
+ compat_uptr_t custom_data;
+};
+
+struct ff_effect_compat {
+ __u16 type;
+ __s16 id;
+ __u16 direction;
+ struct ff_trigger trigger;
+ struct ff_replay replay;
+
+ union {
+ struct ff_constant_effect constant;
+ struct ff_ramp_effect ramp;
+ struct ff_periodic_effect_compat periodic;
+ struct ff_condition_effect condition[2]; /* One for each axis */
+ struct ff_rumble_effect rumble;
+ } u;
+};
+
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
@@ -368,6 +397,42 @@ static int evdev_event_to_user(char __user *buffer,
return 0;
}
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+ struct ff_effect *effect)
+{
+ if (COMPAT_TEST) {
+ struct ff_effect_compat *compat_effect;
+
+ if (size != sizeof(struct ff_effect_compat))
+ return -EINVAL;
+
+ /*
+ * It so happens that the pointer which needs to be changed
+ * is the last field in the structure, so we can copy the
+ * whole thing and replace just the pointer.
+ */
+
+ compat_effect = (struct ff_effect_compat *)effect;
+
+ if (copy_from_user(compat_effect, buffer,
+ sizeof(struct ff_effect_compat)))
+ return -EFAULT;
+
+ if (compat_effect->type == FF_PERIODIC &&
+ compat_effect->u.periodic.waveform == FF_CUSTOM)
+ effect->u.periodic.custom_data =
+ compat_ptr(compat_effect->u.periodic.custom_data);
+ } else {
+ if (size != sizeof(struct ff_effect))
+ return -EINVAL;
+
+ if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
#else
static inline size_t evdev_event_size(void)
@@ -393,6 +458,18 @@ static int evdev_event_to_user(char __user *buffer,
return 0;
}
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+ struct ff_effect *effect)
+{
+ if (size != sizeof(struct ff_effect))
+ return -EINVAL;
+
+ if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+ return -EFAULT;
+
+ return 0;
+}
+
#endif /* CONFIG_COMPAT */
static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -633,17 +710,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return input_set_keycode(dev, t, v);
- case EVIOCSFF:
- if (copy_from_user(&effect, p, sizeof(effect)))
- return -EFAULT;
-
- error = input_ff_upload(dev, &effect, file);
-
- if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
- return -EFAULT;
-
- return error;
-
case EVIOCRMFF:
return input_ff_erase(dev, (int)(unsigned long) p, file);
@@ -733,6 +799,19 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (_IOC_DIR(cmd) == _IOC_WRITE) {
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
+
+ if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+ return -EFAULT;
+
+ error = input_ff_upload(dev, &effect, file);
+
+ if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+ return -EFAULT;
+
+ return error;
+ }
+
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
t = _IOC_NR(cmd) & ABS_MAX;
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index d226d935b0d..6790e975a98 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -247,9 +247,9 @@ static void ml_combine_effects(struct ff_effect *effect,
* in s8, this should be changed to something more generic
*/
effect->u.ramp.start_level =
- max(min(effect->u.ramp.start_level + x, 0x7f), -0x80);
+ clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f);
effect->u.ramp.end_level =
- max(min(effect->u.ramp.end_level + y, 0x7f), -0x80);
+ clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f);
break;
case FF_RUMBLE:
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index 9793ac36d17..b04930f7ea7 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -1,6 +1,4 @@
/*
- * $Id: emu10k1-gp.c,v 1.8 2002/01/22 20:40:46 vojtech Exp $
- *
* Copyright (c) 2001 Vojtech Pavlik
*/
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index c5600ac5feb..078e4eed089 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -36,7 +36,6 @@ EXPORT_SYMBOL(__gameport_register_driver);
EXPORT_SYMBOL(gameport_unregister_driver);
EXPORT_SYMBOL(gameport_open);
EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_rescan);
EXPORT_SYMBOL(gameport_set_phys);
EXPORT_SYMBOL(gameport_start_polling);
EXPORT_SYMBOL(gameport_stop_polling);
@@ -230,8 +229,6 @@ static void gameport_find_driver(struct gameport *gameport)
*/
enum gameport_event_type {
- GAMEPORT_RESCAN,
- GAMEPORT_RECONNECT,
GAMEPORT_REGISTER_PORT,
GAMEPORT_REGISTER_DRIVER,
};
@@ -365,15 +362,6 @@ static void gameport_handle_event(void)
gameport_add_port(event->object);
break;
- case GAMEPORT_RECONNECT:
- gameport_reconnect_port(event->object);
- break;
-
- case GAMEPORT_RESCAN:
- gameport_disconnect_port(event->object);
- gameport_find_driver(event->object);
- break;
-
case GAMEPORT_REGISTER_DRIVER:
gameport_add_driver(event->object);
break;
@@ -651,16 +639,6 @@ static void gameport_disconnect_port(struct gameport *gameport)
device_release_driver(&gameport->dev);
}
-void gameport_rescan(struct gameport *gameport)
-{
- gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
-}
-
-void gameport_reconnect(struct gameport *gameport)
-{
- gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
-}
-
/*
* Submits register request to kgameportd for subsequent execution.
* Note that port registration is always asynchronous.
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
index 6b4d4561d46..06ad36ed348 100644
--- a/drivers/input/gameport/lightning.c
+++ b/drivers/input/gameport/lightning.c
@@ -1,6 +1,4 @@
/*
- * $Id: lightning.c,v 1.20 2002/01/22 20:41:31 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 7b7a546323c..2b282cde4b8 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -1,6 +1,4 @@
/*
- * $Id: ns558.c,v 1.43 2002/01/24 19:23:21 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
* Copyright (c) 1999 Brian Gerst
*/
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 408df0bd6be..c13ced3e0d3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -242,7 +242,7 @@ static void input_handle_event(struct input_dev *dev,
break;
}
- if (type != EV_SYN)
+ if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = 0;
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 52ba16f487c..92498d470b1 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -1,6 +1,4 @@
/*
- * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index deb9f825f92..05022f07ec7 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -1,6 +1,4 @@
/*
- * $Id: amijoy.c,v 1.13 2002/01/22 20:26:32 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 55646a6d89f..639b975a8ed 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -1,6 +1,4 @@
/*
- * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 960e501c60c..52395948475 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -1,6 +1,4 @@
/*
- * $Id: db9.c,v 1.13 2002/04/07 20:13:37 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 1f6302c0eb3..cb6eef1f2d9 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -1,6 +1,4 @@
/*
- * $Id: gf2k.c,v 1.19 2002/01/22 20:27:43 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index fd3853ab1aa..684e07cfccc 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -1,6 +1,4 @@
/*
- * $Id: grip.c,v 1.21 2002/01/22 20:27:57 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index c57e21d68c0..8279481b16e 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -1,6 +1,4 @@
/*
- * $Id: grip_mp.c,v 1.9 2002/07/20 19:28:45 bonnland Exp $
- *
* Driver for the Gravis Grip Multiport, a gamepad "hub" that
* connects up to four 9-pin digital gamepads/joysticks.
* Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index aa6bfb3fb8c..25ec3fad9f2 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -1,6 +1,4 @@
/*
- * $Id: guillemot.c,v 1.10 2002/01/22 20:28:12 vojtech Exp $
- *
* Copyright (c) 2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index f2a4381d0ab..7839b7b6fa9 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -1,6 +1,4 @@
/*
- * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
- *
* Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
*
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index a2517fa72eb..61ee6e38739 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -1,6 +1,4 @@
/*
- * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
- *
* Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
*
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 45c4939ced7..015b50aa76f 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -1,6 +1,4 @@
/*
- * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
- *
* Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
*
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 7b4bc19cef2..46d5041d2d9 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -1,6 +1,4 @@
/*
- * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
*
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 7fb3cf81cfb..851cc4087c2 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -1,6 +1,4 @@
/*
- * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
- *
* Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
*
@@ -89,10 +87,10 @@ static void iforce_usb_irq(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
return;
default:
- dbg("%s - urb has status of: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb has status of: %d", __func__, urb->status);
goto exit;
}
@@ -103,7 +101,7 @@ exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ __func__, status);
}
static void iforce_usb_out(struct urb *urb)
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index a964a7cfd21..f2d91f4028c 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -1,6 +1,4 @@
/*
- * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
- *
* Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
* Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
*
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index bc8ea95dfd0..8c3290b6820 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -1,6 +1,4 @@
/*
- * $Id: interact.c,v 1.16 2002/01/22 20:28:25 vojtech Exp $
- *
* Copyright (c) 2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 88ec5a918f2..2a1b82c8b31 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -1,6 +1,4 @@
/*
- * $Id: joydump.c,v 1.1 2002/01/23 06:56:16 jsimmons Exp $
- *
* Copyright (c) 1996-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 54e676948eb..40e40780747 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -1,6 +1,4 @@
/*
- * $Id: magellan.c,v 1.16 2002/01/22 20:28:39 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index d4087fd4965..0cd9b29356a 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -1,6 +1,4 @@
/*
- * $Id: spaceball.c,v 1.17 2002/01/22 20:29:03 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index f7ce4004f4b..a694bf8e557 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -1,6 +1,4 @@
/*
- * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index baa10b2f7ba..e0db9f5e4b4 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -1,6 +1,4 @@
/*
- * $Id: stinger.c,v 1.10 2002/01/22 20:29:31 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2000 Mark Fletcher
*/
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 0feeb8acb53..60c37bcb938 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -1,6 +1,4 @@
/*
- * $Id: tmdc.c,v 1.31 2002/01/22 20:29:52 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 989483f5316..b6f85986954 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -1,6 +1,4 @@
/*
- * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
- *
* Copyright (c) 1998-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 1085c841fec..3f4ec73c955 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -1,8 +1,4 @@
/*
- * $Id: twidjoy.c,v 1.5 2002/01/22 20:31:53 vojtech Exp $
- *
- * derived from CVS-ID "stinger.c,v 1.5 2001/05/29 12:57:18 vojtech Exp"
- *
* Copyright (c) 2001 Arndt Schoenewald
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2000 Mark Fletcher
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index e928b6e3724..f72c83e15e6 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -1,6 +1,4 @@
/*
- * $Id: warrior.c,v 1.14 2002/01/22 20:32:10 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index b29e3affb80..87d3e7eabff 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -418,11 +418,11 @@ static void xpad_irq_in(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
+ __func__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, status);
+ __func__, status);
goto exit;
}
@@ -441,7 +441,7 @@ exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
static void xpad_bulk_out(struct urb *urb)
@@ -477,11 +477,11 @@ static void xpad_irq_out(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
+ __func__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, status);
+ __func__, status);
goto exit;
}
@@ -489,7 +489,7 @@ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 81bf7562aca..35149ec455a 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -1,6 +1,4 @@
/*
- * $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index af58a6f1e89..b1ce10f50bc 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and
* are loadable via an userland utility.
*/
-static unsigned char atkbd_set2_keycode[512] = {
+static const unsigned short atkbd_set2_keycode[512] = {
#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
@@ -99,7 +99,7 @@ static unsigned char atkbd_set2_keycode[512] = {
#endif
};
-static unsigned char atkbd_set3_keycode[512] = {
+static const unsigned short atkbd_set3_keycode[512] = {
0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60,
131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62,
@@ -115,7 +115,7 @@ static unsigned char atkbd_set3_keycode[512] = {
148,149,147,140
};
-static unsigned char atkbd_unxlate_table[128] = {
+static const unsigned short atkbd_unxlate_table[128] = {
0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
@@ -161,7 +161,7 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_SCR_LEFT 249
#define ATKBD_SCR_RIGHT 248
-#define ATKBD_SPECIAL 248
+#define ATKBD_SPECIAL ATKBD_SCR_RIGHT
#define ATKBD_LED_EVENT_BIT 0
#define ATKBD_REP_EVENT_BIT 1
@@ -173,7 +173,7 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_XL_HANGEUL 0x10
#define ATKBD_XL_HANJA 0x20
-static struct {
+static const struct {
unsigned char keycode;
unsigned char set2;
} atkbd_scroll_keys[] = {
@@ -200,7 +200,7 @@ struct atkbd {
char phys[32];
unsigned short id;
- unsigned char keycode[512];
+ unsigned short keycode[512];
DECLARE_BITMAP(force_release_mask, 512);
unsigned char set;
unsigned char translated;
@@ -357,7 +357,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
unsigned int code = data;
int scroll = 0, hscroll = 0, click = -1;
int value;
- unsigned char keycode;
+ unsigned short keycode;
#ifdef ATKBD_DEBUG
printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
@@ -851,6 +851,23 @@ static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
}
/*
+ * Perform fixup for HP system that doesn't generate release
+ * for its video switch
+ */
+static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
+{
+ const unsigned int forced_release_keys[] = {
+ 0x94,
+ };
+ int i;
+
+ if (atkbd->set == 2)
+ for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+ __set_bit(forced_release_keys[i],
+ atkbd->force_release_mask);
+}
+
+/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -961,16 +978,16 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
input_dev->evbit[0] |= BIT_MASK(EV_REL);
input_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
BIT_MASK(REL_HWHEEL);
- set_bit(BTN_MIDDLE, input_dev->keybit);
+ __set_bit(BTN_MIDDLE, input_dev->keybit);
}
input_dev->keycode = atkbd->keycode;
- input_dev->keycodesize = sizeof(unsigned char);
+ input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
for (i = 0; i < 512; i++)
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
- set_bit(atkbd->keycode[i], input_dev->keybit);
+ __set_bit(atkbd->keycode[i], input_dev->keybit);
}
/*
@@ -1452,6 +1469,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_fixup,
.driver_data = atkbd_latitude_keymap_fixup,
},
+ {
+ .ident = "HP 2133",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"),
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_hp_keymap_fixup,
+ },
{ }
};
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index bbd00c3fe98..be58730e636 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -26,23 +26,54 @@
#include <asm/gpio.h>
+struct gpio_button_data {
+ struct gpio_keys_button *button;
+ struct input_dev *input;
+ struct timer_list timer;
+};
+
+struct gpio_keys_drvdata {
+ struct input_dev *input;
+ struct gpio_button_data data[0];
+};
+
+static void gpio_keys_report_event(struct gpio_keys_button *button,
+ struct input_dev *input)
+{
+ unsigned int type = button->type ?: EV_KEY;
+ int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
+
+ input_event(input, type, button->code, !!state);
+ input_sync(input);
+}
+
+static void gpio_check_button(unsigned long _data)
+{
+ struct gpio_button_data *data = (struct gpio_button_data *)_data;
+
+ gpio_keys_report_event(data->button, data->input);
+}
+
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
- int i;
struct platform_device *pdev = dev_id;
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
- struct input_dev *input = platform_get_drvdata(pdev);
+ struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+ int i;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
- int gpio = button->gpio;
- if (irq == gpio_to_irq(gpio)) {
- unsigned int type = button->type ?: EV_KEY;
- int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
+ if (irq == gpio_to_irq(button->gpio)) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+
+ if (button->debounce_interval)
+ mod_timer(&bdata->timer,
+ jiffies +
+ msecs_to_jiffies(button->debounce_interval));
+ else
+ gpio_keys_report_event(button, bdata->input);
- input_event(input, type, button->code, !!state);
- input_sync(input);
return IRQ_HANDLED;
}
}
@@ -53,17 +84,21 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ struct gpio_keys_drvdata *ddata;
struct input_dev *input;
int i, error;
int wakeup = 0;
+ ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
+ pdata->nbuttons * sizeof(struct gpio_button_data),
+ GFP_KERNEL);
input = input_allocate_device();
- if (!input)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, input);
+ if (!ddata || !input) {
+ error = -ENOMEM;
+ goto fail1;
+ }
- input->evbit[0] = BIT_MASK(EV_KEY);
+ platform_set_drvdata(pdev, ddata);
input->name = pdev->name;
input->phys = "gpio-keys/input0";
@@ -74,16 +109,23 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0100;
+ ddata->input = input;
+
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
+ struct gpio_button_data *bdata = &ddata->data[i];
int irq;
unsigned int type = button->type ?: EV_KEY;
+ bdata->input = input;
+ setup_timer(&bdata->timer,
+ gpio_check_button, (unsigned long)bdata);
+
error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
if (error < 0) {
pr_err("gpio-keys: failed to request GPIO %d,"
" error %d\n", button->gpio, error);
- goto fail;
+ goto fail2;
}
error = gpio_direction_input(button->gpio);
@@ -92,7 +134,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
" direction for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
- goto fail;
+ goto fail2;
}
irq = gpio_to_irq(button->gpio);
@@ -102,7 +144,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
" for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
- goto fail;
+ goto fail2;
}
error = request_irq(irq, gpio_keys_isr,
@@ -114,7 +156,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
gpio_free(button->gpio);
- goto fail;
+ goto fail2;
}
if (button->wakeup)
@@ -127,21 +169,25 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
if (error) {
pr_err("gpio-keys: Unable to register input device, "
"error: %d\n", error);
- goto fail;
+ goto fail2;
}
device_init_wakeup(&pdev->dev, wakeup);
return 0;
- fail:
+ fail2:
while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+ if (pdata->buttons[i].debounce_interval)
+ del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio);
}
platform_set_drvdata(pdev, NULL);
+ fail1:
input_free_device(input);
+ kfree(ddata);
return error;
}
@@ -149,7 +195,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
static int __devexit gpio_keys_remove(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
- struct input_dev *input = platform_get_drvdata(pdev);
+ struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+ struct input_dev *input = ddata->input;
int i;
device_init_wakeup(&pdev->dev, 0);
@@ -157,6 +204,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, pdev);
+ if (pdata->buttons[i].debounce_interval)
+ del_timer_sync(&ddata->data[i].timer);
gpio_free(pdata->buttons[i].gpio);
}
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index adbf29f0169..71c1971abf8 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/pci_ids.h>
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 32e2c2605d9..4730ef35c73 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -538,11 +538,11 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
switch (code) {
case SND_CLICK:
if (value == 0) {
- DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
+ DBG ("%s: Deactivating key clicks\n", __func__);
lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
} else {
- DBG ("%s: Activating key clicks\n", __FUNCTION__);
+ DBG ("%s: Activating key clicks\n", __func__);
lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -560,7 +560,7 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
default:
printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
- __FUNCTION__, type, code, value);
+ __func__, type, code, value);
}
return -1;
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 45767e73f07..6f1516f5075 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -105,6 +105,8 @@ struct pxa27x_keypad {
struct input_dev *input_dev;
void __iomem *mmio_base;
+ int irq;
+
/* matrix key code map */
unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
@@ -392,6 +394,10 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
clk_disable(keypad->clk);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(keypad->irq);
+
return 0;
}
@@ -400,6 +406,9 @@ static int pxa27x_keypad_resume(struct platform_device *pdev)
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev;
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(keypad->irq);
+
mutex_lock(&input_dev->mutex);
if (input_dev->users) {
@@ -509,6 +518,8 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
goto failed_free_dev;
}
+ keypad->irq = irq;
+
/* Register the input device */
error = input_register_device(input_dev);
if (error) {
@@ -516,6 +527,8 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
goto failed_free_irq;
}
+ device_init_wakeup(&pdev->dev, 1);
+
return 0;
failed_free_irq:
@@ -539,7 +552,7 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
struct resource *res;
- free_irq(platform_get_irq(pdev, 0), pdev);
+ free_irq(keypad->irq, pdev);
clk_disable(keypad->clk);
clk_put(keypad->clk);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index be0f5d19d02..9fce6d1e29b 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -1,6 +1,4 @@
/*
- * $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
index 94e444b4ee1..b12b7ee4b6a 100644
--- a/drivers/input/keyboard/tosakbd.c
+++ b/drivers/input/keyboard/tosakbd.c
@@ -215,8 +215,6 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
unsigned long flags;
spin_lock_irqsave(&tosakbd->lock, flags);
- PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
- PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
tosakbd->suspended = 1;
spin_unlock_irqrestore(&tosakbd->lock, flags);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 152a2c07050..37b01d777a4 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -1,6 +1,4 @@
/*
- * $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 432699d61c5..e99b7882f38 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -189,6 +189,16 @@ config INPUT_UINPUT
To compile this driver as a module, choose M here: the
module will be called uinput.
+config INPUT_SGI_BTNS
+ tristate "SGI Indy/O2 volume button interface"
+ depends on SGI_IP22 || SGI_IP32
+ select INPUT_POLLDEV
+ help
+ Say Y here if you want to support SGI Indy/O2 volume button interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sgi_btns.
+
config HP_SDC_RTC
tristate "HP SDC Real Time Clock"
depends on GSC || HP300
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ebd39f291d2..f48009b5222 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
+obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c
index f3b86c2b079..debfc1af9d9 100644
--- a/drivers/input/misc/ati_remote.c
+++ b/drivers/input/misc/ati_remote.c
@@ -330,7 +330,7 @@ static int ati_remote_open(struct input_dev *inputdev)
ati_remote->irq_urb->dev = ati_remote->udev;
if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
dev_err(&ati_remote->interface->dev,
- "%s: usb_submit_urb failed!\n", __FUNCTION__);
+ "%s: usb_submit_urb failed!\n", __func__);
return -EIO;
}
@@ -356,7 +356,7 @@ static void ati_remote_irq_out(struct urb *urb)
if (urb->status) {
dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
return;
}
@@ -601,17 +601,17 @@ static void ati_remote_irq_in(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
- __FUNCTION__);
+ __func__);
return;
default: /* error */
dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
}
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
- __FUNCTION__, retval);
+ __func__, retval);
}
/*
@@ -734,7 +734,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
int err = -ENOMEM;
if (iface_host->desc.bNumEndpoints != 2) {
- err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
+ err("%s: Unexpected desc.bNumEndpoints\n", __func__);
return -ENODEV;
}
@@ -742,11 +742,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
endpoint_out = &iface_host->endpoint[1].desc;
if (!usb_endpoint_is_int_in(endpoint_in)) {
- err("%s: Unexpected endpoint_in\n", __FUNCTION__);
+ err("%s: Unexpected endpoint_in\n", __func__);
return -ENODEV;
}
if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
- err("%s: endpoint_in message size==0? \n", __FUNCTION__);
+ err("%s: endpoint_in message size==0? \n", __func__);
return -ENODEV;
}
@@ -814,7 +814,7 @@ static void ati_remote_disconnect(struct usb_interface *interface)
ati_remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!ati_remote) {
- warn("%s - null device?\n", __FUNCTION__);
+ warn("%s - null device?\n", __func__);
return;
}
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index f2709b82485..a7fabafbd94 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -137,14 +137,14 @@ static int ati_remote2_open(struct input_dev *idev)
r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
if (r) {
dev_err(&ar2->intf[0]->dev,
- "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+ "%s: usb_submit_urb() = %d\n", __func__, r);
return r;
}
r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
if (r) {
usb_kill_urb(ar2->urb[0]);
dev_err(&ar2->intf[1]->dev,
- "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+ "%s: usb_submit_urb() = %d\n", __func__, r);
return r;
}
@@ -294,17 +294,17 @@ static void ati_remote2_complete_mouse(struct urb *urb)
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&ar2->intf[0]->dev,
- "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ "%s(): urb status = %d\n", __func__, urb->status);
return;
default:
dev_err(&ar2->intf[0]->dev,
- "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ "%s(): urb status = %d\n", __func__, urb->status);
}
r = usb_submit_urb(urb, GFP_ATOMIC);
if (r)
dev_err(&ar2->intf[0]->dev,
- "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+ "%s(): usb_submit_urb() = %d\n", __func__, r);
}
static void ati_remote2_complete_key(struct urb *urb)
@@ -321,17 +321,17 @@ static void ati_remote2_complete_key(struct urb *urb)
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&ar2->intf[1]->dev,
- "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ "%s(): urb status = %d\n", __func__, urb->status);
return;
default:
dev_err(&ar2->intf[1]->dev,
- "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ "%s(): urb status = %d\n", __func__, urb->status);
}
r = usb_submit_urb(urb, GFP_ATOMIC);
if (r)
dev_err(&ar2->intf[1]->dev,
- "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+ "%s(): usb_submit_urb() = %d\n", __func__, r);
}
static int ati_remote2_input_init(struct ati_remote2 *ar2)
@@ -438,7 +438,7 @@ static int ati_remote2_setup(struct ati_remote2 *ar2)
channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT);
if (r) {
dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n",
- __FUNCTION__, r);
+ __func__, r);
return r;
}
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 49d8abfe38f..daa9d422033 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -44,6 +44,7 @@
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/rtc.h>
+#include <linux/semaphore.h>
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index 952938a8e99..86afdd1fdf9 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -159,7 +159,7 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
if (dev->data.pos >= dev->data.len) {
dev_dbg(&dev->udev->dev,
"%s - Error ran out of data. pos: %d, len: %d\n",
- __FUNCTION__, dev->data.pos, dev->data.len);
+ __func__, dev->data.pos, dev->data.len);
return -1;
}
@@ -267,7 +267,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Unknown sequence found in system data.\n", __FUNCTION__);
+ err("%s - Unknown sequence found in system data.\n", __func__);
remote->stage = 0;
return;
}
@@ -286,7 +286,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Unknown sequence found in button data.\n", __FUNCTION__);
+ err("%s - Unknown sequence found in button data.\n", __func__);
remote->stage = 0;
return;
}
@@ -302,7 +302,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
remote->data.tester = remote->data.tester >> 6;
remote->data.bits_left -= 6;
} else {
- err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+ err("%s - Error in message, invalid toggle.\n", __func__);
remote->stage = 0;
return;
}
@@ -317,7 +317,7 @@ static void keyspan_check_data(struct usb_keyspan *remote)
dev_dbg(&remote->udev->dev,
"%s found valid message: system: %d, button: %d, toggle: %d\n",
- __FUNCTION__, message.system, message.button, message.toggle);
+ __func__, message.system, message.button, message.toggle);
if (message.toggle != remote->toggle) {
keyspan_report_button(remote, message.button, 1);
@@ -341,7 +341,7 @@ static int keyspan_setup(struct usb_device* dev)
0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
- __FUNCTION__, retval);
+ __func__, retval);
return(retval);
}
@@ -349,7 +349,7 @@ static int keyspan_setup(struct usb_device* dev)
0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
- __FUNCTION__, retval);
+ __func__, retval);
return(retval);
}
@@ -357,11 +357,11 @@ static int keyspan_setup(struct usb_device* dev)
0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
if (retval) {
dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
- __FUNCTION__, retval);
+ __func__, retval);
return(retval);
}
- dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__);
+ dev_dbg(&dev->dev, "%s - Setup complete.\n", __func__);
return(retval);
}
@@ -397,7 +397,7 @@ static void keyspan_irq_recv(struct urb *urb)
resubmit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval);
+ err ("%s - usb_submit_urb failed with result: %d", __func__, retval);
}
static int keyspan_open(struct input_dev *dev)
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 7a7b8c7b963..a53c4885fba 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -96,10 +96,10 @@ static void powermate_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto exit;
}
@@ -112,7 +112,7 @@ exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
/* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
new file mode 100644
index 00000000000..ce238f59b3c
--- /dev/null
+++ b/drivers/input/misc/sgi_btns.c
@@ -0,0 +1,178 @@
+/*
+ * SGI Volume Button interface driver
+ *
+ * Copyright (C) 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_SGI_IP22
+#include <asm/sgi/ioc.h>
+
+static inline u8 button_status(void)
+{
+ u8 status;
+
+ status = readb(&sgioc->panel) ^ 0xa0;
+ return ((status & 0x80) >> 6) | ((status & 0x20) >> 5);
+}
+#endif
+
+#ifdef CONFIG_SGI_IP32
+#include <asm/ip32/mace.h>
+
+static inline u8 button_status(void)
+{
+ u64 status;
+
+ status = readq(&mace->perif.audio.control);
+ writeq(status & ~(3U << 23), &mace->perif.audio.control);
+
+ return (status >> 23) & 3;
+}
+#endif
+
+#define BUTTONS_POLL_INTERVAL 30 /* msec */
+#define BUTTONS_COUNT_THRESHOLD 3
+
+static const unsigned short sgi_map[] = {
+ KEY_VOLUMEDOWN,
+ KEY_VOLUMEUP
+};
+
+struct buttons_dev {
+ struct input_polled_dev *poll_dev;
+ unsigned short keymap[ARRAY_SIZE(sgi_map)];
+ int count[ARRAY_SIZE(sgi_map)];
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+ struct buttons_dev *bdev = dev->private;
+ struct input_dev *input = dev->input;
+ u8 status;
+ int i;
+
+ status = button_status();
+
+ for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
+ if (status & (1U << i)) {
+ if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
+ input_event(input, EV_MSC, MSC_SCAN, i);
+ input_report_key(input, bdev->keymap[i], 1);
+ input_sync(input);
+ }
+ } else {
+ if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
+ input_event(input, EV_MSC, MSC_SCAN, i);
+ input_report_key(input, bdev->keymap[i], 0);
+ input_sync(input);
+ }
+ bdev->count[i] = 0;
+ }
+ }
+}
+
+static int __devinit sgi_buttons_probe(struct platform_device *pdev)
+{
+ struct buttons_dev *bdev;
+ struct input_polled_dev *poll_dev;
+ struct input_dev *input;
+ int error, i;
+
+ bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+ poll_dev = input_allocate_polled_device();
+ if (!bdev || !poll_dev) {
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
+
+ poll_dev->private = bdev;
+ poll_dev->poll = handle_buttons;
+ poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+ input = poll_dev->input;
+ input->name = "SGI buttons";
+ input->phys = "sgi/input0";
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+
+ input->keycode = bdev->keymap;
+ input->keycodemax = ARRAY_SIZE(bdev->keymap);
+ input->keycodesize = sizeof(unsigned short);
+
+ input_set_capability(input, EV_MSC, MSC_SCAN);
+ __set_bit(EV_KEY, input->evbit);
+ for (i = 0; i < ARRAY_SIZE(sgi_map); i++)
+ __set_bit(bdev->keymap[i], input->keybit);
+ __clear_bit(KEY_RESERVED, input->keybit);
+
+ bdev->poll_dev = poll_dev;
+ dev_set_drvdata(&pdev->dev, bdev);
+
+ error = input_register_polled_device(poll_dev);
+ if (error)
+ goto err_free_mem;
+
+ return 0;
+
+ err_free_mem:
+ input_free_polled_device(poll_dev);
+ kfree(bdev);
+ dev_set_drvdata(&pdev->dev, NULL);
+ return error;
+}
+
+static int __devexit sgi_buttons_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+ input_unregister_polled_device(bdev->poll_dev);
+ input_free_polled_device(bdev->poll_dev);
+ kfree(bdev);
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver sgi_buttons_driver = {
+ .probe = sgi_buttons_probe,
+ .remove = __devexit_p(sgi_buttons_remove),
+ .driver = {
+ .name = "sgibtns",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sgi_buttons_init(void)
+{
+ return platform_driver_register(&sgi_buttons_driver);
+}
+
+static void __exit sgi_buttons_exit(void)
+{
+ platform_driver_unregister(&sgi_buttons_driver);
+}
+
+module_init(sgi_buttons_init);
+module_exit(sgi_buttons_exit);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 72176f3d49c..fe268be3293 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -1186,7 +1186,7 @@ static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
static int __devinit setup_input_dev(void)
{
- const struct key_entry *key;
+ struct key_entry *key;
struct input_dev *input_dev;
int error;
@@ -1219,6 +1219,23 @@ static int __devinit setup_input_dev(void)
set_bit(key->sw.code, input_dev->swbit);
break;
+ /* if wifi or bluetooth are not available, create normal keys */
+ case KE_WIFI:
+ if (!have_wifi) {
+ key->type = KE_KEY;
+ key->keycode = KEY_WLAN;
+ key--;
+ }
+ break;
+
+ case KE_BLUETOOTH:
+ if (!have_bluetooth) {
+ key->type = KE_KEY;
+ key->keycode = KEY_BLUETOOTH;
+ key--;
+ }
+ break;
+
default:
break;
}
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 46279ef2b64..facefd3dba2 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -119,6 +119,8 @@ struct yealink_dev {
u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
int key_code; /* last reported key */
+ unsigned int shutdown:1;
+
int stat_ix;
union {
struct yld_status s;
@@ -424,10 +426,10 @@ send_update:
static void urb_irq_callback(struct urb *urb)
{
struct yealink_dev *yld = urb->context;
- int ret;
+ int ret, status = urb->status;
- if (urb->status)
- err("%s - urb status %d", __FUNCTION__, urb->status);
+ if (status)
+ err("%s - urb status %d", __func__, status);
switch (yld->irq_data->cmd) {
case CMD_KEYPRESS:
@@ -447,33 +449,38 @@ static void urb_irq_callback(struct urb *urb)
yealink_do_idle_tasks(yld);
- ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
- if (ret)
- err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+ if (!yld->shutdown) {
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (ret && ret != -EPERM)
+ err("%s - usb_submit_urb failed %d", __func__, ret);
+ }
}
static void urb_ctl_callback(struct urb *urb)
{
struct yealink_dev *yld = urb->context;
- int ret;
+ int ret = 0, status = urb->status;
- if (urb->status)
- err("%s - urb status %d", __FUNCTION__, urb->status);
+ if (status)
+ err("%s - urb status %d", __func__, status);
switch (yld->ctl_data->cmd) {
case CMD_KEYPRESS:
case CMD_SCANCODE:
/* ask for a response */
- ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+ if (!yld->shutdown)
+ ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
break;
default:
/* send new command */
yealink_do_idle_tasks(yld);
- ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (!yld->shutdown)
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ break;
}
- if (ret)
- err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+ if (ret && ret != -EPERM)
+ err("%s - usb_submit_urb failed %d", __func__, ret);
}
/*******************************************************************************
@@ -505,7 +512,7 @@ static int input_open(struct input_dev *dev)
struct yealink_dev *yld = input_get_drvdata(dev);
int i, ret;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* force updates to device */
for (i = 0; i<sizeof(yld->master); i++)
@@ -521,7 +528,7 @@ static int input_open(struct input_dev *dev)
yld->ctl_data->sum = 0x100-CMD_INIT-10;
if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
dbg("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, ret);
+ __func__, ret);
return ret;
}
return 0;
@@ -531,8 +538,18 @@ static void input_close(struct input_dev *dev)
{
struct yealink_dev *yld = input_get_drvdata(dev);
+ yld->shutdown = 1;
+ /*
+ * Make sure the flag is seen by other CPUs before we start
+ * killing URBs so new URBs won't be submitted
+ */
+ smp_wmb();
+
usb_kill_urb(yld->urb_ctl);
usb_kill_urb(yld->urb_irq);
+
+ yld->shutdown = 0;
+ smp_wmb();
}
/*******************************************************************************
@@ -809,9 +826,6 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
if (yld == NULL)
return err;
- usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */
- usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */
-
if (yld->idev) {
if (err)
input_free_device(yld->idev);
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index ce6fdec19e1..1f41ae94f26 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -2,12 +2,13 @@
* Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver
*
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
* Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
* Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
+ * Copyright (C) 2007-2008 Sven Anders (anders@anduras.de)
*
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
*
@@ -34,77 +35,64 @@
#include <linux/module.h>
#include <linux/usb/input.h>
-/* Apple has powerbooks which have the keyboard with different Product IDs */
-#define APPLE_VENDOR_ID 0x05AC
-
-/* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E
-#define FOUNTAIN_ISO_PRODUCT_ID 0x020F
-
-#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A
-
-#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B
-
-#define GEYSER_ANSI_PRODUCT_ID 0x0214
-#define GEYSER_ISO_PRODUCT_ID 0x0215
-#define GEYSER_JIS_PRODUCT_ID 0x0216
-
-/* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID 0x0217
-#define GEYSER3_ISO_PRODUCT_ID 0x0218
-#define GEYSER3_JIS_PRODUCT_ID 0x0219
-
-/*
- * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
- * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
- */
-#define GEYSER4_ANSI_PRODUCT_ID 0x021A
-#define GEYSER4_ISO_PRODUCT_ID 0x021B
-#define GEYSER4_JIS_PRODUCT_ID 0x021C
-
-#define GEYSER4_HF_ANSI_PRODUCT_ID 0x0229
-#define GEYSER4_HF_ISO_PRODUCT_ID 0x022A
-#define GEYSER4_HF_JIS_PRODUCT_ID 0x022B
+/* Type of touchpad */
+enum atp_touchpad_type {
+ ATP_FOUNTAIN,
+ ATP_GEYSER1,
+ ATP_GEYSER2,
+ ATP_GEYSER3,
+ ATP_GEYSER4
+};
-#define ATP_DEVICE(prod) \
+#define ATP_DEVICE(prod, type) \
+{ \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
- .idVendor = APPLE_VENDOR_ID, \
+ .idVendor = 0x05ac, /* Apple */ \
.idProduct = (prod), \
.bInterfaceClass = 0x03, \
- .bInterfaceProtocol = 0x02
+ .bInterfaceProtocol = 0x02, \
+ .driver_info = ATP_ ## type, \
+}
+
+/*
+ * Table of devices (Product IDs) that work with this driver.
+ * (The names come from Info.plist in AppleUSBTrackpad.kext,
+ * According to Info.plist Geyser IV is the same as Geyser III.)
+ */
-/* table of devices that work with this driver */
static struct usb_device_id atp_table [] = {
- { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
- { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
- { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
+ /* PowerBooks Feb 2005, iBooks G4 */
+ ATP_DEVICE(0x020e, FOUNTAIN), /* FOUNTAIN ANSI */
+ ATP_DEVICE(0x020f, FOUNTAIN), /* FOUNTAIN ISO */
+ ATP_DEVICE(0x030a, FOUNTAIN), /* FOUNTAIN TP ONLY */
+ ATP_DEVICE(0x030b, GEYSER1), /* GEYSER 1 TP ONLY */
/* PowerBooks Oct 2005 */
- { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+ ATP_DEVICE(0x0214, GEYSER2), /* GEYSER 2 ANSI */
+ ATP_DEVICE(0x0215, GEYSER2), /* GEYSER 2 ISO */
+ ATP_DEVICE(0x0216, GEYSER2), /* GEYSER 2 JIS */
/* Core Duo MacBook & MacBook Pro */
- { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+ ATP_DEVICE(0x0217, GEYSER3), /* GEYSER 3 ANSI */
+ ATP_DEVICE(0x0218, GEYSER3), /* GEYSER 3 ISO */
+ ATP_DEVICE(0x0219, GEYSER3), /* GEYSER 3 JIS */
/* Core2 Duo MacBook & MacBook Pro */
- { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+ ATP_DEVICE(0x021a, GEYSER4), /* GEYSER 4 ANSI */
+ ATP_DEVICE(0x021b, GEYSER4), /* GEYSER 4 ISO */
+ ATP_DEVICE(0x021c, GEYSER4), /* GEYSER 4 JIS */
- { ATP_DEVICE(GEYSER4_HF_ANSI_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER4_HF_ISO_PRODUCT_ID) },
- { ATP_DEVICE(GEYSER4_HF_JIS_PRODUCT_ID) },
+ /* Core2 Duo MacBook3,1 */
+ ATP_DEVICE(0x0229, GEYSER4), /* GEYSER 4 HF ANSI */
+ ATP_DEVICE(0x022a, GEYSER4), /* GEYSER 4 HF ISO */
+ ATP_DEVICE(0x022b, GEYSER4), /* GEYSER 4 HF JIS */
/* Terminating entry */
{ }
};
-MODULE_DEVICE_TABLE (usb, atp_table);
+MODULE_DEVICE_TABLE(usb, atp_table);
/*
* number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -124,9 +112,13 @@ MODULE_DEVICE_TABLE (usb, atp_table);
* We try to keep the touchpad aspect ratio while still doing only simple
* arithmetics.
* The factors below give coordinates like:
- * 0 <= x < 960 on 12" and 15" Powerbooks
- * 0 <= x < 1600 on 17" Powerbooks
- * 0 <= y < 646
+ *
+ * 0 <= x < 960 on 12" and 15" Powerbooks
+ * 0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
+ * 0 <= x < 1216 on MacBooks and 15" MacBook Pro
+ *
+ * 0 <= y < 646 on all Powerbooks
+ * 0 <= y < 774 on all MacBooks
*/
#define ATP_XFACT 64
#define ATP_YFACT 43
@@ -147,43 +139,46 @@ MODULE_DEVICE_TABLE (usb, atp_table);
/* Structure to hold all of our device specific stuff */
struct atp {
char phys[64];
- struct usb_device * udev; /* usb device */
- struct urb * urb; /* usb request block */
- signed char * data; /* transferred data */
- struct input_dev * input; /* input dev */
- unsigned char open; /* non-zero if opened */
- unsigned char valid; /* are the sensors valid ? */
- unsigned char size_detect_done;
- unsigned char overflowwarn; /* overflow warning printed? */
+ struct usb_device *udev; /* usb device */
+ struct urb *urb; /* usb request block */
+ signed char *data; /* transferred data */
+ struct input_dev *input; /* input dev */
+ enum atp_touchpad_type type; /* type of touchpad */
+ bool open;
+ bool valid; /* are the samples valid? */
+ bool size_detect_done;
+ bool overflow_warned;
int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */
- /* current value of the sensors */
signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
- /* last value of the sensors */
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
- /* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
- int datalen; /* size of an USB urb transfer */
- int idlecount; /* number of empty packets */
- struct work_struct work;
+ int datalen; /* size of USB transfer */
+ int idlecount; /* number of empty packets */
+ struct work_struct work;
};
#define dbg_dump(msg, tab) \
if (debug > 1) { \
- int i; \
- printk("appletouch: %s %lld", msg, (long long)jiffies); \
- for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
- printk(" %02x", tab[i]); \
+ int __i; \
+ printk(KERN_DEBUG "appletouch: %s", msg); \
+ for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++) \
+ printk(" %02x", tab[__i]); \
printk("\n"); \
}
#define dprintk(format, a...) \
do { \
- if (debug) printk(KERN_DEBUG format, ##a); \
+ if (debug) \
+ printk(KERN_DEBUG format, ##a); \
} while (0)
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
-MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_AUTHOR("Johannes Berg");
+MODULE_AUTHOR("Stelian Pop");
+MODULE_AUTHOR("Frank Arnold");
+MODULE_AUTHOR("Michael Hanselmann");
+MODULE_AUTHOR("Sven Anders");
+MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver");
MODULE_LICENSE("GPL");
/*
@@ -191,46 +186,14 @@ MODULE_LICENSE("GPL");
*/
static int threshold = ATP_THRESHOLD;
module_param(threshold, int, 0644);
-MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor"
+ " (the trackpad has many of these sensors)"
+ " less than this value.");
-static int debug = 1;
+static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
-static inline int atp_is_fountain(struct atp *dev)
-{
- u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
- return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
- productId == FOUNTAIN_ISO_PRODUCT_ID ||
- productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
-}
-
-/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
-static inline int atp_is_geyser_2(struct atp *dev)
-{
- u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
- return (productId == GEYSER_ANSI_PRODUCT_ID) ||
- (productId == GEYSER_ISO_PRODUCT_ID) ||
- (productId == GEYSER_JIS_PRODUCT_ID);
-}
-
-static inline int atp_is_geyser_3(struct atp *dev)
-{
- u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
- return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
- (productId == GEYSER3_ISO_PRODUCT_ID) ||
- (productId == GEYSER3_JIS_PRODUCT_ID) ||
- (productId == GEYSER4_ANSI_PRODUCT_ID) ||
- (productId == GEYSER4_ISO_PRODUCT_ID) ||
- (productId == GEYSER4_JIS_PRODUCT_ID) ||
- (productId == GEYSER4_HF_ANSI_PRODUCT_ID) ||
- (productId == GEYSER4_HF_ISO_PRODUCT_ID) ||
- (productId == GEYSER4_HF_JIS_PRODUCT_ID);
-}
-
/*
* By default newer Geyser devices send standard USB HID mouse
* packets (Report ID 2). This code changes device mode, so it
@@ -240,6 +203,7 @@ static int atp_geyser_init(struct usb_device *udev)
{
char data[8];
int size;
+ int i;
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ATP_GEYSER_MODE_READ_REQUEST_ID,
@@ -248,8 +212,11 @@ static int atp_geyser_init(struct usb_device *udev)
ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) {
- err("Could not do mode read request from device"
- " (Geyser Raw mode)");
+ dprintk("atp_geyser_init: read error\n");
+ for (i = 0; i < 8; i++)
+ dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+ err("Failed to read mode from device.");
return -EIO;
}
@@ -263,8 +230,11 @@ static int atp_geyser_init(struct usb_device *udev)
ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) {
- err("Could not do mode write request to device"
- " (Geyser Raw mode)");
+ dprintk("atp_geyser_init: write error\n");
+ for (i = 0; i < 8; i++)
+ dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+ err("Failed to request geyser raw mode");
return -EIO;
}
return 0;
@@ -280,15 +250,15 @@ static void atp_reinit(struct work_struct *work)
struct usb_device *udev = dev->udev;
int retval;
+ dprintk("appletouch: putting appletouch to sleep (reinit)\n");
dev->idlecount = 0;
atp_geyser_init(udev);
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
- if (retval) {
- err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
- }
+ if (retval)
+ err("atp_reinit: usb_submit_urb failed with error %d",
+ retval);
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -323,7 +293,8 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
*
* - Jason Parekh <jasonparekh@gmail.com>
*/
- if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
+ if (i < 1 ||
+ (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
(*fingers)++;
is_increasing = 1;
} else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
@@ -331,11 +302,11 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
}
/*
- * Subtracts threshold so a high sensor that just passes the threshold
- * won't skew the calculated absolute coordinate. Fixes an issue
- * where slowly moving the mouse would occassionaly jump a number of
- * pixels (let me restate--slowly moving the mouse makes this issue
- * most apparent).
+ * Subtracts threshold so a high sensor that just passes the
+ * threshold won't skew the calculated absolute coordinate.
+ * Fixes an issue where slowly moving the mouse would
+ * occasionally jump a number of pixels (slowly moving the
+ * finger makes this issue most apparent.)
*/
pcum += (xy_sensors[i] - threshold) * i;
psum += (xy_sensors[i] - threshold);
@@ -356,7 +327,7 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
}
-static void atp_complete(struct urb* urb)
+static void atp_complete(struct urb *urb)
{
int x, y, x_z, y_z, x_f, y_f;
int retval, i, j;
@@ -368,22 +339,22 @@ static void atp_complete(struct urb* urb)
/* success */
break;
case -EOVERFLOW:
- if(!dev->overflowwarn) {
+ if (!dev->overflow_warned) {
printk(KERN_WARNING "appletouch: OVERFLOW with data "
"length %d, actual length is %d\n",
dev->datalen, dev->urb->actual_length);
- dev->overflowwarn = 1;
+ dev->overflow_warned = true;
}
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* This urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ dbg("atp_complete: urb shutting down with status: %d",
+ urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ dbg("atp_complete: nonzero urb status received: %d",
+ urb->status);
goto exit;
}
@@ -396,7 +367,7 @@ static void atp_complete(struct urb* urb)
}
/* reorder the sensors values */
- if (atp_is_geyser_3(dev)) {
+ if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
/*
@@ -415,7 +386,7 @@ static void atp_complete(struct urb* urb)
dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
}
- } else if (atp_is_geyser_2(dev)) {
+ } else if (dev->type == ATP_GEYSER2) {
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
/*
@@ -438,7 +409,7 @@ static void atp_complete(struct urb* urb)
} else {
for (i = 0; i < 8; i++) {
/* X values */
- dev->xy_cur[i ] = dev->data[5 * i + 2];
+ dev->xy_cur[i + 0] = dev->data[5 * i + 2];
dev->xy_cur[i + 8] = dev->data[5 * i + 4];
dev->xy_cur[i + 16] = dev->data[5 * i + 42];
if (i < 2)
@@ -454,21 +425,22 @@ static void atp_complete(struct urb* urb)
if (!dev->valid) {
/* first sample */
- dev->valid = 1;
+ dev->valid = true;
dev->x_old = dev->y_old = -1;
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
if (dev->size_detect_done ||
- atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+ dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */
goto exit;
/* 17" Powerbooks have extra X sensors */
- for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
+ for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
+ i < ATP_XSENSORS; i++) {
if (!dev->xy_cur[i])
continue;
printk(KERN_INFO "appletouch: 17\" model detected.\n");
- if (atp_is_geyser_2(dev))
+ if (dev->type == ATP_GEYSER2)
input_set_abs_params(dev->input, ABS_X, 0,
(20 - 1) *
ATP_XFACT - 1,
@@ -548,11 +520,15 @@ static void atp_complete(struct urb* urb)
* several hundred times a second. Re-initialization does not
* work on Fountain touchpads.
*/
- if (!atp_is_fountain(dev)) {
+ if (dev->type != ATP_FOUNTAIN) {
+ /*
+ * Button must not be pressed when entering suspend,
+ * otherwise we will never release the button.
+ */
if (!x && !y && !key) {
dev->idlecount++;
if (dev->idlecount == 10) {
- dev->valid = 0;
+ dev->valid = false;
schedule_work(&dev->work);
/* Don't resubmit urb here, wait for reinit */
return;
@@ -561,12 +537,11 @@ static void atp_complete(struct urb* urb)
dev->idlecount = 0;
}
-exit:
+ exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
- if (retval) {
- err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
- }
+ if (retval)
+ err("atp_complete: usb_submit_urb failed with result %d",
+ retval);
}
static int atp_open(struct input_dev *input)
@@ -593,7 +568,7 @@ static int atp_handle_geyser(struct atp *dev)
{
struct usb_device *udev = dev->udev;
- if (!atp_is_fountain(dev)) {
+ if (dev->type != ATP_FOUNTAIN) {
/* switch to raw sensor mode */
if (atp_geyser_init(udev))
return -EIO;
@@ -604,7 +579,8 @@ static int atp_handle_geyser(struct atp *dev)
return 0;
}
-static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+static int atp_probe(struct usb_interface *iface,
+ const struct usb_device_id *id)
{
struct atp *dev;
struct input_dev *input_dev;
@@ -640,13 +616,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
dev->udev = udev;
dev->input = input_dev;
- dev->overflowwarn = 0;
- if (atp_is_geyser_3(dev))
- dev->datalen = 64;
- else if (atp_is_geyser_2(dev))
- dev->datalen = 64;
- else
+ dev->type = id->driver_info;
+ dev->overflow_warned = false;
+ if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1)
dev->datalen = 81;
+ else
+ dev->datalen = 64;
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb)
@@ -680,7 +655,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
set_bit(EV_ABS, input_dev->evbit);
- if (atp_is_geyser_3(dev)) {
+ if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
/*
* MacBook have 20 X sensors, 10 Y sensors
*/
@@ -688,7 +663,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
input_set_abs_params(input_dev, ABS_Y, 0,
((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
- } else if (atp_is_geyser_2(dev)) {
+ } else if (dev->type == ATP_GEYSER2) {
/*
* Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
* later.
@@ -703,9 +678,11 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
* 17" models are detected later.
*/
input_set_abs_params(input_dev, ABS_X, 0,
- (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+ (16 - 1) * ATP_XFACT - 1,
+ ATP_FUZZ, 0);
input_set_abs_params(input_dev, ABS_Y, 0,
- (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+ (ATP_YSENSORS - 1) * ATP_YFACT - 1,
+ ATP_FUZZ, 0);
}
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
@@ -774,7 +751,7 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message)
struct atp *dev = usb_get_intfdata(iface);
usb_kill_urb(dev->urb);
- dev->valid = 0;
+ dev->valid = false;
return 0;
}
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
index 98a3561d4b0..adf45b3040e 100644
--- a/drivers/input/mouse/atarimouse.c
+++ b/drivers/input/mouse/atarimouse.c
@@ -57,15 +57,12 @@ MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
MODULE_DESCRIPTION("Atari mouse driver");
MODULE_LICENSE("GPL");
-static int mouse_threshold[2] = {2,2};
+static int mouse_threshold[2] = {2, 2};
+module_param_array(mouse_threshold, int, NULL, 0);
-#ifdef __MODULE__
-MODULE_PARM(mouse_threshold, "2i");
-#endif
#ifdef FIXED_ATARI_JOYSTICK
extern int atari_mouse_buttons;
#endif
-static int atamouse_used = 0;
static struct input_dev *atamouse_dev;
@@ -97,9 +94,6 @@ static void atamouse_interrupt(char *buf)
static int atamouse_open(struct input_dev *dev)
{
- if (atamouse_used++)
- return 0;
-
#ifdef FIXED_ATARI_JOYSTICK
atari_mouse_buttons = 0;
#endif
@@ -107,23 +101,24 @@ static int atamouse_open(struct input_dev *dev)
ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
ikbd_mouse_rel_pos();
atari_input_mouse_interrupt_hook = atamouse_interrupt;
+
return 0;
}
static void atamouse_close(struct input_dev *dev)
{
- if (!--atamouse_used) {
- ikbd_mouse_disable();
- atari_mouse_interrupt_hook = NULL;
- }
+ ikbd_mouse_disable();
+ atari_mouse_interrupt_hook = NULL;
}
static int __init atamouse_init(void)
{
+ int error;
+
if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
return -ENODEV;
- if (!(atari_keyb_init()))
+ if (!atari_keyb_init())
return -ENODEV;
atamouse_dev = input_allocate_device();
@@ -141,12 +136,14 @@ static int __init atamouse_init(void)
atamouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
atamouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+
atamouse_dev->open = atamouse_open;
atamouse_dev->close = atamouse_close;
- if (input_register_device(atamouse_dev)) {
+ error = input_register_device(atamouse_dev);
+ if (error) {
input_free_device(atamouse_dev);
- return -ENOMEM;
+ return error;
}
return 0;
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index 27f88fbb713..e532c48410e 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -247,19 +247,24 @@ static void hil_ptr_disconnect(struct serio *serio)
static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
{
- struct hil_ptr *ptr;
- const char *txt;
- unsigned int i, naxsets, btntype;
- uint8_t did, *idd;
-
- if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL)))
+ struct hil_ptr *ptr;
+ const char *txt;
+ unsigned int i, naxsets, btntype;
+ uint8_t did, *idd;
+ int error;
+
+ ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL);
+ if (!ptr)
return -ENOMEM;
ptr->dev = input_allocate_device();
- if (!ptr->dev)
+ if (!ptr->dev) {
+ error = -ENOMEM;
goto bail0;
+ }
- if (serio_open(serio, driver))
+ error = serio_open(serio, driver);
+ if (error)
goto bail1;
serio_set_drvdata(serio, ptr);
@@ -297,6 +302,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
did = ptr->idd[0];
idd = ptr->idd + 1;
txt = "unknown";
+
if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
ptr->dev->evbit[0] = BIT_MASK(EV_REL);
txt = "relative";
@@ -306,8 +312,11 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
ptr->dev->evbit[0] = BIT_MASK(EV_ABS);
txt = "absolute";
}
- if (!ptr->dev->evbit[0])
+
+ if (!ptr->dev->evbit[0]) {
+ error = -ENODEV;
goto bail2;
+ }
ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
if (ptr->nbtn)
@@ -380,13 +389,19 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */
ptr->dev->dev.parent = &serio->dev;
- input_register_device(ptr->dev);
+ error = input_register_device(ptr->dev);
+ if (error) {
+ printk(KERN_INFO PREFIX "Unable to register input device\n");
+ goto bail2;
+ }
+
printk(KERN_INFO "input: %s (%s), ID: %d\n",
ptr->dev->name,
(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
did);
return 0;
+
bail2:
serio_close(serio);
bail1:
@@ -394,7 +409,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
bail0:
kfree(ptr);
serio_set_drvdata(serio, NULL);
- return -ENODEV;
+ return error;
}
static struct serio_device_id hil_ptr_ids[] = {
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 06c35fc553c..3827a22362d 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -1,6 +1,4 @@
/*
- * $Id: inport.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 9ea895593b2..e2413113df2 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -1,6 +1,4 @@
/*
- * $Id: logibm.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 61cff8374e6..fd09c8df81f 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -1,6 +1,4 @@
/*
- * $Id: pc110pad.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index ed917bfd086..17ff137b9bd 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -1,6 +1,4 @@
/*
- * $Id: sermouse.c,v 1.17 2002/03/13 10:03:43 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index ec4b6610f73..27d70d326ff 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -190,4 +190,14 @@ config SERIO_RAW
To compile this driver as a module, choose M here: the
module will be called serio_raw.
+config SERIO_XILINX_XPS_PS2
+ tristate "Xilinx XPS PS/2 Controller Support"
+ depends on PPC
+ help
+ This driver supports XPS PS/2 IP from the Xilinx EDK on
+ PowerPC platform.
+
+ To compile this driver as a module, choose M here: the
+ module will be called xilinx_ps2.
+
endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 38b886887cb..9b6c8135955 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
obj-$(CONFIG_SERIO_RAW) += serio_raw.o
+obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 0d35018c23a..d1380fc72cc 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -1,6 +1,4 @@
/*
- * $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 93a1a6ba216..37586a68d34 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -76,7 +76,7 @@ static struct timer_list hil_mlcs_kicker;
static int hil_mlcs_probe;
static void hil_mlcs_process(unsigned long unused);
-DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
/* #define HIL_MLC_DEBUG */
@@ -459,7 +459,7 @@ static int hilse_operate(hil_mlc *mlc, int repoll)
#define OUT_LAST(pack) \
{ HILSE_OUT_LAST, { .packet = pack }, 0, 0, 0, 0 },
-const struct hilse_node hil_mlc_se[HILSEN_END] = {
+static const struct hilse_node hil_mlc_se[HILSEN_END] = {
/* 0 HILSEN_START */
FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0)
@@ -784,7 +784,7 @@ static void hil_mlcs_process(unsigned long unused)
/************************* Keepalive timer task *********************/
-void hil_mlcs_timer(unsigned long data)
+static void hil_mlcs_timer(unsigned long data)
{
hil_mlcs_probe = 1;
tasklet_schedule(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index edfedd9a166..aad664d5259 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -67,6 +67,7 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/time.h>
+#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/hil.h>
#include <linux/semaphore.h>
@@ -105,6 +106,10 @@ EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
+static unsigned int hp_sdc_disabled;
+module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
+MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
+
static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */
/*************** primitives for use in any context *********************/
@@ -980,6 +985,11 @@ static int __init hp_sdc_register(void)
unsigned char i;
#endif
+ if (hp_sdc_disabled) {
+ printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
+ return -ENODEV;
+ }
+
hp_sdc.dev = NULL;
hp_sdc.dev_err = 0;
#if defined(__hppa__)
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index 587398f5c9d..b587e2d576a 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -50,7 +50,7 @@ MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
MODULE_LICENSE("Dual BSD/GPL");
-struct hp_sdc_mlc_priv_s {
+static struct hp_sdc_mlc_priv_s {
int emtestmode;
hp_sdc_transaction trans;
u8 tseq[16];
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 78eb7841174..fe732a574ec 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -63,13 +63,22 @@ static inline void i8042_write_command(int val)
outb(val, I8042_COMMAND_REG);
}
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
#include <linux/dmi.h>
static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
{
/* AUX LOOP command does not raise AUX IRQ */
+ .ident = "Arima-Rioworks HDAMB",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
+ DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
+ DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
+ },
+ },
+ {
+ /* AUX LOOP command does not raise AUX IRQ */
.ident = "ASUS P65UP5",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
@@ -118,6 +127,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
},
},
+ {
+ .ident = "Medion MAM 2070",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+ },
+ },
{ }
};
@@ -291,17 +308,36 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
},
},
+ {
+ .ident = "Acer Aspire 1360",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+ },
+ },
+ {
+ .ident = "Gericom Bellagio",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+ },
+ },
{ }
};
-
-
+#ifdef CONFIG_PNP
+static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
+ {
+ .ident = "Intel MBO Desktop D845PESV",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ },
+ },
+ { }
+};
#endif
-#ifdef CONFIG_X86
-
-#include <linux/dmi.h>
-
/*
* Some Wistron based laptops need us to explicitly enable the 'Dritek
* keyboard extension' to make their extra keys start generating scancodes.
@@ -331,6 +367,13 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
},
},
{
+ .ident = "Acer Aspire 5720",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+ },
+ },
+ {
.ident = "Acer Aspire 9110",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -356,7 +399,6 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
#endif /* CONFIG_X86 */
-
#ifdef CONFIG_PNP
#include <linux/pnp.h>
@@ -466,6 +508,11 @@ static int __init i8042_pnp_init(void)
int pnp_data_busted = 0;
int err;
+#ifdef CONFIG_X86
+ if (dmi_check_system(i8042_dmi_nopnp_table))
+ i8042_nopnp = 1;
+#endif
+
if (i8042_nopnp) {
printk(KERN_INFO "i8042: PNP detection disabled\n");
return 0;
@@ -591,15 +638,13 @@ static int __init i8042_platform_init(void)
i8042_reset = 1;
#endif
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
if (dmi_check_system(i8042_dmi_noloop_table))
i8042_noloop = 1;
if (dmi_check_system(i8042_dmi_nomux_table))
i8042_nomux = 1;
-#endif
-#ifdef CONFIG_X86
if (dmi_check_system(i8042_dmi_dritek_table))
i8042_dritek = 1;
#endif /* CONFIG_X86 */
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index b819239d74d..2b304c22c20 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -26,15 +26,6 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
MODULE_DESCRIPTION("PS/2 driver library");
MODULE_LICENSE("GPL");
-/* Work structure to schedule execution of a command */
-struct ps2work {
- struct work_struct work;
- struct ps2dev *ps2dev;
- int command;
- unsigned char param[0];
-};
-
-
/*
* ps2_sendbyte() sends a byte to the device and waits for acknowledge.
* It doesn't handle retransmission, though it could - because if there
@@ -246,49 +237,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
EXPORT_SYMBOL(ps2_command);
/*
- * ps2_execute_scheduled_command() sends a command, previously scheduled by
- * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.)
- */
-
-static void ps2_execute_scheduled_command(struct work_struct *work)
-{
- struct ps2work *ps2work = container_of(work, struct ps2work, work);
-
- ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command);
- kfree(ps2work);
-}
-
-/*
- * ps2_schedule_command() allows to schedule delayed execution of a PS/2
- * command and can be used to issue a command from an interrupt or softirq
- * context.
- */
-
-int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command)
-{
- struct ps2work *ps2work;
- int send = (command >> 12) & 0xf;
- int receive = (command >> 8) & 0xf;
-
- if (!(ps2work = kmalloc(sizeof(struct ps2work) + max(send, receive), GFP_ATOMIC)))
- return -1;
-
- memset(ps2work, 0, sizeof(struct ps2work));
- ps2work->ps2dev = ps2dev;
- ps2work->command = command;
- memcpy(ps2work->param, param, send);
- INIT_WORK(&ps2work->work, ps2_execute_scheduled_command);
-
- if (!schedule_work(&ps2work->work)) {
- kfree(ps2work);
- return -1;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(ps2_schedule_command);
-
-/*
* ps2_init() initializes ps2dev structure
*/
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index d962a8d78b1..e36a0901646 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -1,6 +1,4 @@
/*
- * $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
@@ -49,7 +47,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
MODULE_LICENSE("GPL");
-DEFINE_SPINLOCK(q40kbd_lock);
+static DEFINE_SPINLOCK(q40kbd_lock);
static struct serio *q40kbd_port;
static struct platform_device *q40kbd_device;
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 34c59d9c620..1567b778247 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -1,6 +1,4 @@
/*
- * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2002 Russell King
*/
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 7f5293828fb..78f2abb5c11 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -331,9 +331,10 @@ static void serio_handle_event(void)
}
/*
- * Remove all events that have been submitted for a given serio port.
+ * Remove all events that have been submitted for a given
+ * object, be it serio port or driver.
*/
-static void serio_remove_pending_events(struct serio *serio)
+static void serio_remove_pending_events(void *object)
{
struct list_head *node, *next;
struct serio_event *event;
@@ -343,7 +344,7 @@ static void serio_remove_pending_events(struct serio *serio)
list_for_each_safe(node, next, &serio_event_list) {
event = list_entry(node, struct serio_event, node);
- if (event->object == serio) {
+ if (event->object == object) {
list_del_init(node);
serio_free_event(event);
}
@@ -837,7 +838,9 @@ void serio_unregister_driver(struct serio_driver *drv)
struct serio *serio;
mutex_lock(&serio_mutex);
+
drv->manual_bind = 1; /* so serio_find_driver ignores it */
+ serio_remove_pending_events(drv);
start_over:
list_for_each_entry(serio, &serio_list, node) {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
new file mode 100644
index 00000000000..0ed044d5e68
--- /dev/null
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -0,0 +1,380 @@
+/*
+ * Xilinx XPS PS/2 device driver
+ *
+ * (c) 2005 MontaVista Software, Inc.
+ * (c) 2008 Xilinx, Inc.
+ *
+ * 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.
+ *
+ * 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/serio.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define DRIVER_NAME "xilinx_ps2"
+
+/* Register offsets for the xps2 device */
+#define XPS2_SRST_OFFSET 0x00000000 /* Software Reset register */
+#define XPS2_STATUS_OFFSET 0x00000004 /* Status register */
+#define XPS2_RX_DATA_OFFSET 0x00000008 /* Receive Data register */
+#define XPS2_TX_DATA_OFFSET 0x0000000C /* Transmit Data register */
+#define XPS2_GIER_OFFSET 0x0000002C /* Global Interrupt Enable reg */
+#define XPS2_IPISR_OFFSET 0x00000030 /* Interrupt Status register */
+#define XPS2_IPIER_OFFSET 0x00000038 /* Interrupt Enable register */
+
+/* Reset Register Bit Definitions */
+#define XPS2_SRST_RESET 0x0000000A /* Software Reset */
+
+/* Status Register Bit Positions */
+#define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */
+#define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */
+
+/* Bit definitions for ISR/IER registers. Both the registers have the same bit
+ * definitions and are only defined once. */
+#define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */
+#define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */
+#define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */
+#define XPS2_IPIXR_RX_OVF 0x00000008 /* Receive Overflow Interrupt */
+#define XPS2_IPIXR_RX_ERR 0x00000010 /* Receive Error Interrupt */
+#define XPS2_IPIXR_RX_FULL 0x00000020 /* Receive Data Interrupt */
+
+/* Mask for all the Transmit Interrupts */
+#define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
+
+/* Mask for all the Receive Interrupts */
+#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
+ XPS2_IPIXR_RX_FULL)
+
+/* Mask for all the Interrupts */
+#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
+ XPS2_IPIXR_WDT_TOUT)
+
+/* Global Interrupt Enable mask */
+#define XPS2_GIER_GIE_MASK 0x80000000
+
+struct xps2data {
+ int irq;
+ u32 phys_addr;
+ u32 remap_size;
+ spinlock_t lock;
+ u8 rxb; /* Rx buffer */
+ void __iomem *base_address; /* virt. address of control registers */
+ unsigned int dfl;
+ struct serio serio; /* serio */
+};
+
+/************************************/
+/* XPS PS/2 data transmission calls */
+/************************************/
+
+/*
+ * xps2_recv() will attempt to receive a byte of data from the PS/2 port.
+ */
+static int xps2_recv(struct xps2data *drvdata, u8 *byte)
+{
+ u32 sr;
+ int status = -1;
+
+ /* If there is data available in the PS/2 receiver, read it */
+ sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+ if (sr & XPS2_STATUS_RX_FULL) {
+ *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
+ status = 0;
+ }
+
+ return status;
+}
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static irqreturn_t xps2_interrupt(int irq, void *dev_id)
+{
+ struct xps2data *drvdata = dev_id;
+ u32 intr_sr;
+ u8 c;
+ int status;
+
+ /* Get the PS/2 interrupts and clear them */
+ intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
+ out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
+
+ /* Check which interrupt is active */
+ if (intr_sr & XPS2_IPIXR_RX_OVF)
+ printk(KERN_WARNING "%s: receive overrun error\n",
+ drvdata->serio.name);
+
+ if (intr_sr & XPS2_IPIXR_RX_ERR)
+ drvdata->dfl |= SERIO_PARITY;
+
+ if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
+ drvdata->dfl |= SERIO_TIMEOUT;
+
+ if (intr_sr & XPS2_IPIXR_RX_FULL) {
+ status = xps2_recv(drvdata, &drvdata->rxb);
+
+ /* Error, if a byte is not received */
+ if (status) {
+ printk(KERN_ERR
+ "%s: wrong rcvd byte count (%d)\n",
+ drvdata->serio.name, status);
+ } else {
+ c = drvdata->rxb;
+ serio_interrupt(&drvdata->serio, c, drvdata->dfl);
+ drvdata->dfl = 0;
+ }
+ }
+
+ if (intr_sr & XPS2_IPIXR_TX_ACK)
+ drvdata->dfl = 0;
+
+ return IRQ_HANDLED;
+}
+
+/*******************/
+/* serio callbacks */
+/*******************/
+
+/*
+ * sxps2_write() sends a byte out through the PS/2 interface.
+ */
+static int sxps2_write(struct serio *pserio, unsigned char c)
+{
+ struct xps2data *drvdata = pserio->port_data;
+ unsigned long flags;
+ u32 sr;
+ int status = -1;
+
+ spin_lock_irqsave(&drvdata->lock, flags);
+
+ /* If the PS/2 transmitter is empty send a byte of data */
+ sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+ if (!(sr & XPS2_STATUS_TX_FULL)) {
+ out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
+ status = 0;
+ }
+
+ spin_unlock_irqrestore(&drvdata->lock, flags);
+
+ return status;
+}
+
+/*
+ * sxps2_open() is called when a port is open by the higher layer.
+ */
+static int sxps2_open(struct serio *pserio)
+{
+ struct xps2data *drvdata = pserio->port_data;
+ int retval;
+
+ retval = request_irq(drvdata->irq, &xps2_interrupt, 0,
+ DRIVER_NAME, drvdata);
+ if (retval) {
+ printk(KERN_ERR
+ "%s: Couldn't allocate interrupt %d\n",
+ drvdata->serio.name, drvdata->irq);
+ return retval;
+ }
+
+ /* start reception by enabling the interrupts */
+ out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
+ out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
+ (void)xps2_recv(drvdata, &drvdata->rxb);
+
+ return 0; /* success */
+}
+
+/*
+ * sxps2_close() frees the interrupt.
+ */
+static void sxps2_close(struct serio *pserio)
+{
+ struct xps2data *drvdata = pserio->port_data;
+
+ /* Disable the PS2 interrupts */
+ out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
+ out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
+ free_irq(drvdata->irq, drvdata);
+}
+
+/*********************/
+/* Device setup code */
+/*********************/
+
+static int xps2_setup(struct device *dev, struct resource *regs_res,
+ struct resource *irq_res)
+{
+ struct xps2data *drvdata;
+ struct serio *serio;
+ unsigned long remap_size;
+ int retval;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (!regs_res || !irq_res) {
+ dev_err(dev, "IO resource(s) not found\n");
+ return -EINVAL;
+ }
+
+ drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
+ if (!drvdata) {
+ dev_err(dev, "Couldn't allocate device private record\n");
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, drvdata);
+
+ spin_lock_init(&drvdata->lock);
+ drvdata->irq = irq_res->start;
+
+ remap_size = regs_res->end - regs_res->start + 1;
+ if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) {
+ dev_err(dev, "Couldn't lock memory region at 0x%08X\n",
+ (unsigned int)regs_res->start);
+ retval = -EBUSY;
+ goto failed1;
+ }
+
+ /* Fill in configuration data and add them to the list */
+ drvdata->phys_addr = regs_res->start;
+ drvdata->remap_size = remap_size;
+ drvdata->base_address = ioremap(regs_res->start, remap_size);
+ if (drvdata->base_address == NULL) {
+ dev_err(dev, "Couldn't ioremap memory at 0x%08X\n",
+ (unsigned int)regs_res->start);
+ retval = -EFAULT;
+ goto failed2;
+ }
+
+ /* Disable all the interrupts, just in case */
+ out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
+
+ /* Reset the PS2 device and abort any current transaction, to make sure
+ * we have the PS2 in a good state */
+ out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
+
+ dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n",
+ drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq);
+
+ serio = &drvdata->serio;
+ serio->id.type = SERIO_8042;
+ serio->write = sxps2_write;
+ serio->open = sxps2_open;
+ serio->close = sxps2_close;
+ serio->port_data = drvdata;
+ serio->dev.parent = dev;
+ snprintf(serio->name, sizeof(serio->name),
+ "Xilinx XPS PS/2 at %08X", drvdata->phys_addr);
+ snprintf(serio->phys, sizeof(serio->phys),
+ "xilinxps2/serio at %08X", drvdata->phys_addr);
+ serio_register_port(serio);
+
+ return 0; /* success */
+
+failed2:
+ release_mem_region(regs_res->start, remap_size);
+failed1:
+ kfree(drvdata);
+ dev_set_drvdata(dev, NULL);
+
+ return retval;
+}
+
+/***************************/
+/* OF Platform Bus Support */
+/***************************/
+
+static int __devinit xps2_of_probe(struct of_device *ofdev, const struct
+ of_device_id * match)
+{
+ struct resource r_irq; /* Interrupt resources */
+ struct resource r_mem; /* IO mem resources */
+ int rc = 0;
+
+ printk(KERN_INFO "Device Tree Probing \'%s\'\n",
+ ofdev->node->name);
+
+ /* Get iospace for the device */
+ rc = of_address_to_resource(ofdev->node, 0, &r_mem);
+ if (rc) {
+ dev_err(&ofdev->dev, "invalid address\n");
+ return rc;
+ }
+
+ /* Get IRQ for the device */
+ rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
+ if (rc == NO_IRQ) {
+ dev_err(&ofdev->dev, "no IRQ found\n");
+ return rc;
+ }
+
+ return xps2_setup(&ofdev->dev, &r_mem, &r_irq);
+}
+
+static int __devexit xps2_of_remove(struct of_device *of_dev)
+{
+ struct device *dev = &of_dev->dev;
+ struct xps2data *drvdata;
+
+ if (!dev)
+ return -EINVAL;
+
+ drvdata = dev_get_drvdata(dev);
+
+ serio_unregister_port(&drvdata->serio);
+ iounmap(drvdata->base_address);
+ release_mem_region(drvdata->phys_addr, drvdata->remap_size);
+ kfree(drvdata);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0; /* success */
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id xps2_of_match[] __devinitdata = {
+ { .compatible = "xlnx,xps-ps2-1.00.a", },
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, xps2_of_match);
+
+static struct of_platform_driver xps2_of_driver = {
+ .name = DRIVER_NAME,
+ .match_table = xps2_of_match,
+ .probe = xps2_of_probe,
+ .remove = __devexit_p(xps2_of_remove),
+};
+
+static int __init xps2_init(void)
+{
+ return of_register_platform_driver(&xps2_of_driver);
+}
+
+static void __exit xps2_cleanup(void)
+{
+ of_unregister_platform_driver(&xps2_of_driver);
+}
+
+module_init(xps2_init);
+module_exit(xps2_cleanup);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index b973d0ef6d1..570e0e83ac4 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -73,10 +73,10 @@ static void usb_acecad_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto resubmit;
}
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 55c1134d613..8f037a1d44a 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -449,12 +449,12 @@ static void aiptek_irq(struct urb *urb)
case -ESHUTDOWN:
/* This urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
goto exit;
}
@@ -813,7 +813,7 @@ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval != 0) {
err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
}
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 1e748e46d12..b9b7a98bc5a 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -863,7 +863,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
if (!gtco->urbinfo) {
err("Failed to allocate URB");
- return -ENOMEM;
+ error = -ENOMEM;
goto err_free_buf;
}
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index f23f5a97fb3..d89112fa6e6 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -56,10 +56,10 @@ static void kbtab_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto exit;
}
@@ -88,7 +88,7 @@ static void kbtab_irq(struct urb *urb)
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
static struct usb_device_id kbtab_ids[] = {
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 706619d06f7..ca62ec639f8 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -105,7 +105,7 @@ struct wacom {
struct urb *irq;
struct wacom_wac * wacom_wac;
struct mutex lock;
- int open:1;
+ unsigned int open:1;
char phys[32];
};
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 71cc0c14079..5fbc463baf5 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -56,10 +56,10 @@ static void wacom_sys_irq(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto exit;
}
@@ -74,7 +74,7 @@ static void wacom_sys_irq(struct urb *urb)
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 192513e1f04..bf3d9a8b2c1 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -56,7 +56,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
{
unsigned char *data = wacom->data;
- int prox, id, pressure;
+ int prox, pressure;
if (data[0] != 2) {
dbg("wacom_pl_irq: received unknown report #%d", data[0]);
@@ -65,7 +65,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
prox = data[1] & 0x40;
- id = ERASER_DEVICE_ID;
+ wacom->id[0] = ERASER_DEVICE_ID;
if (prox) {
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
@@ -99,10 +99,10 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
if (wacom->tool[1] != BTN_TOOL_RUBBER) {
/* Unknown tool selected default to pen tool */
wacom->tool[1] = BTN_TOOL_PEN;
- id = STYLUS_DEVICE_ID;
+ wacom->id[0] = STYLUS_DEVICE_ID;
}
wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
- wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
@@ -127,7 +127,6 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
{
unsigned char *data = wacom->data;
- int id;
if (data[0] != 2) {
printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
@@ -137,13 +136,13 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
if (data[1] & 0x04) {
wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
- id = ERASER_DEVICE_ID;
+ wacom->id[0] = ERASER_DEVICE_ID;
} else {
wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
- id = STYLUS_DEVICE_ID;
+ wacom->id[0] = STYLUS_DEVICE_ID;
}
- wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
@@ -155,27 +154,26 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
{
unsigned char *data = wacom->data;
- int x, y, id, rw;
+ int x, y, rw;
if (data[0] != 2) {
dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
return 0;
}
- id = STYLUS_DEVICE_ID;
- if ((data[1] & 0x80) && ((data[1] & 0x07) || data[2] || data[3] || data[4]
- || data[5] || data[6] || (data[7] & 0x07))) {
+ if (data[1] & 0x80) {
/* in prox and not a pad data */
switch ((data[1] >> 5) & 3) {
case 0: /* Pen */
wacom->tool[0] = BTN_TOOL_PEN;
+ wacom->id[0] = STYLUS_DEVICE_ID;
break;
case 1: /* Rubber */
wacom->tool[0] = BTN_TOOL_RUBBER;
- id = ERASER_DEVICE_ID;
+ wacom->id[0] = ERASER_DEVICE_ID;
break;
case 2: /* Mouse with wheel */
@@ -190,7 +188,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case 3: /* Mouse without wheel */
wacom->tool[0] = BTN_TOOL_MOUSE;
- id = CURSOR_DEVICE_ID;
+ wacom->id[0] = CURSOR_DEVICE_ID;
wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
if (wacom->features->type == WACOM_G4 ||
@@ -210,9 +208,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
}
- wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
wacom_report_key(wcombo, wacom->tool[0], 1);
- } else if (!(data[1] & 0x90)) {
+ } else if (wacom->id[0]) {
wacom_report_abs(wcombo, ABS_X, 0);
wacom_report_abs(wcombo, ABS_Y, 0);
if (wacom->tool[0] == BTN_TOOL_MOUSE) {
@@ -225,6 +223,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS, 0);
wacom_report_key(wcombo, BTN_STYLUS2, 0);
}
+ wacom->id[0] = 0;
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
wacom_report_key(wcombo, wacom->tool[0], 0);
}
@@ -234,13 +233,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case WACOM_G4:
if (data[7] & 0xf8) {
wacom_input_sync(wcombo); /* sync last event */
- wacom->id[1] = 1;
+ wacom->id[1] = PAD_DEVICE_ID;
wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
wacom_report_rel(wcombo, REL_WHEEL, rw);
wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
- wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
} else if (wacom->id[1]) {
wacom_input_sync(wcombo); /* sync last event */
@@ -255,14 +254,14 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case WACOM_MO:
if ((data[7] & 0xf8) || (data[8] & 0xff)) {
wacom_input_sync(wcombo); /* sync last event */
- wacom->id[1] = 1;
+ wacom->id[1] = PAD_DEVICE_ID;
wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
- wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
} else if (wacom->id[1]) {
wacom_input_sync(wcombo); /* sync last event */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 565ec711c2e..e5736652157 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -103,6 +103,18 @@ config TOUCHSCREEN_MTOUCH
To compile this driver as a module, choose M here: the
module will be called mtouch.
+config TOUCHSCREEN_INEXIO
+ tristate "iNexio serial touchscreens"
+ select SERIO
+ help
+ Say Y here if you have an iNexio serial touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called inexio.
+
config TOUCHSCREEN_MK712
tristate "ICS MicroClock MK712 touchscreen"
help
@@ -134,6 +146,18 @@ config TOUCHSCREEN_HP7XX
To compile this driver as a module, choose M here: the
module will be called jornada720_ts.
+config TOUCHSCREEN_HTCPEN
+ tristate "HTC Shift X9500 touchscreen"
+ depends on ISA
+ help
+ Say Y here if you have an HTC Shift UMPC also known as HTC X9500
+ Clio / Shangrila and want to support the built-in touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called htcpen.
+
config TOUCHSCREEN_PENMOUNT
tristate "Penmount serial touchscreen"
select SERIO
@@ -146,6 +170,17 @@ config TOUCHSCREEN_PENMOUNT
To compile this driver as a module, choose M here: the
module will be called penmount.
+config TOUCHSCREEN_MIGOR
+ tristate "Renesas MIGO-R touchscreen"
+ depends on SH_MIGOR && I2C
+ help
+ Say Y here to enable MIGO-R touchscreen support.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called migor_ts.
+
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
@@ -316,4 +351,15 @@ config TOUCHSCREEN_USB_GOTOP
bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
+config TOUCHSCREEN_TOUCHIT213
+ tristate "Sahara TouchIT-213 touchscreen"
+ select SERIO
+ help
+ Say Y here if you have a Sahara TouchIT-213 Tablet PC.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called touchit213.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3c096d75651..39a804cd80f 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -12,12 +12,16 @@ obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
+obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
+obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index a48a15868c4..a54f90e02ab 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -1,6 +1,4 @@
/*
- * $Id: gunze.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
* Copyright (c) 2000-2001 Vojtech Pavlik
*/
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 28ae15ed12c..4f86081dc7f 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -1,6 +1,4 @@
/*
- * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $
- *
* Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
*
* Sponsored by Transvirtual Technology.
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
new file mode 100644
index 00000000000..62811de6f18
--- /dev/null
+++ b/drivers/input/touchscreen/htcpen.c
@@ -0,0 +1,255 @@
+/*
+ * HTC Shift touchscreen driver
+ *
+ * Copyright (C) 2008 Pau Oliva Fora <pof@eslack.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/isa.h>
+#include <linux/ioport.h>
+#include <linux/dmi.h>
+
+MODULE_AUTHOR("Pau Oliva Fora <pau@eslack.org>");
+MODULE_DESCRIPTION("HTC Shift touchscreen driver");
+MODULE_LICENSE("GPL");
+
+#define HTCPEN_PORT_IRQ_CLEAR 0x068
+#define HTCPEN_PORT_INIT 0x06c
+#define HTCPEN_PORT_INDEX 0x0250
+#define HTCPEN_PORT_DATA 0x0251
+#define HTCPEN_IRQ 3
+
+#define DEVICE_ENABLE 0xa2
+#define DEVICE_DISABLE 0xa3
+
+#define X_INDEX 3
+#define Y_INDEX 5
+#define TOUCH_INDEX 0xb
+#define LSB_XY_INDEX 0xc
+#define X_AXIS_MAX 2040
+#define Y_AXIS_MAX 2040
+
+static int invert_x;
+module_param(invert_x, bool, 0644);
+MODULE_PARM_DESC(invert_x, "If set, X axis is inverted");
+static int invert_y;
+module_param(invert_y, bool, 0644);
+MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted");
+
+static struct pnp_device_id pnp_ids[] = {
+ { .id = "PNP0cc0" },
+ { .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, pnp_ids);
+
+static irqreturn_t htcpen_interrupt(int irq, void *handle)
+{
+ struct input_dev *htcpen_dev = handle;
+ unsigned short x, y, xy;
+
+ /* 0 = press; 1 = release */
+ outb_p(TOUCH_INDEX, HTCPEN_PORT_INDEX);
+
+ if (inb_p(HTCPEN_PORT_DATA)) {
+ input_report_key(htcpen_dev, BTN_TOUCH, 0);
+ } else {
+ outb_p(X_INDEX, HTCPEN_PORT_INDEX);
+ x = inb_p(HTCPEN_PORT_DATA);
+
+ outb_p(Y_INDEX, HTCPEN_PORT_INDEX);
+ y = inb_p(HTCPEN_PORT_DATA);
+
+ outb_p(LSB_XY_INDEX, HTCPEN_PORT_INDEX);
+ xy = inb_p(HTCPEN_PORT_DATA);
+
+ /* get high resolution value of X and Y using LSB */
+ x = X_AXIS_MAX - ((x * 8) + ((xy >> 4) & 0xf));
+ y = (y * 8) + (xy & 0xf);
+ if (invert_x)
+ x = X_AXIS_MAX - x;
+ if (invert_y)
+ y = Y_AXIS_MAX - y;
+
+ if (x != X_AXIS_MAX && x != 0) {
+ input_report_key(htcpen_dev, BTN_TOUCH, 1);
+ input_report_abs(htcpen_dev, ABS_X, x);
+ input_report_abs(htcpen_dev, ABS_Y, y);
+ }
+ }
+
+ input_sync(htcpen_dev);
+
+ inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+ return IRQ_HANDLED;
+}
+
+static int htcpen_open(struct input_dev *dev)
+{
+ outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+ return 0;
+}
+
+static void htcpen_close(struct input_dev *dev)
+{
+ outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+ synchronize_irq(HTCPEN_IRQ);
+}
+
+static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
+{
+ struct input_dev *htcpen_dev;
+ int err = -EBUSY;
+
+ if (!request_region(HTCPEN_PORT_IRQ_CLEAR, 1, "htcpen")) {
+ printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+ HTCPEN_PORT_IRQ_CLEAR);
+ goto request_region1_failed;
+ }
+
+ if (!request_region(HTCPEN_PORT_INIT, 1, "htcpen")) {
+ printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+ HTCPEN_PORT_INIT);
+ goto request_region2_failed;
+ }
+
+ if (!request_region(HTCPEN_PORT_INDEX, 2, "htcpen")) {
+ printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+ HTCPEN_PORT_INDEX);
+ goto request_region3_failed;
+ }
+
+ htcpen_dev = input_allocate_device();
+ if (!htcpen_dev) {
+ printk(KERN_ERR "htcpen: can't allocate device\n");
+ err = -ENOMEM;
+ goto input_alloc_failed;
+ }
+
+ htcpen_dev->name = "HTC Shift EC TouchScreen";
+ htcpen_dev->id.bustype = BUS_ISA;
+
+ htcpen_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ htcpen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(htcpen_dev, ABS_X, 0, X_AXIS_MAX, 0, 0);
+ input_set_abs_params(htcpen_dev, ABS_Y, 0, Y_AXIS_MAX, 0, 0);
+
+ htcpen_dev->open = htcpen_open;
+ htcpen_dev->close = htcpen_close;
+
+ err = request_irq(HTCPEN_IRQ, htcpen_interrupt, 0, "htcpen",
+ htcpen_dev);
+ if (err) {
+ printk(KERN_ERR "htcpen: irq busy\n");
+ goto request_irq_failed;
+ }
+
+ inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+ err = input_register_device(htcpen_dev);
+ if (err)
+ goto input_register_failed;
+
+ dev_set_drvdata(dev, htcpen_dev);
+
+ return 0;
+
+ input_register_failed:
+ free_irq(HTCPEN_IRQ, htcpen_dev);
+ request_irq_failed:
+ input_free_device(htcpen_dev);
+ input_alloc_failed:
+ release_region(HTCPEN_PORT_INDEX, 2);
+ request_region3_failed:
+ release_region(HTCPEN_PORT_INIT, 1);
+ request_region2_failed:
+ release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+ request_region1_failed:
+ return err;
+}
+
+static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id)
+{
+ struct input_dev *htcpen_dev = dev_get_drvdata(dev);
+
+ input_unregister_device(htcpen_dev);
+
+ free_irq(HTCPEN_IRQ, htcpen_dev);
+
+ release_region(HTCPEN_PORT_INDEX, 2);
+ release_region(HTCPEN_PORT_INIT, 1);
+ release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int htcpen_isa_suspend(struct device *dev, unsigned int n,
+ pm_message_t state)
+{
+ outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+
+ return 0;
+}
+
+static int htcpen_isa_resume(struct device *dev, unsigned int n)
+{
+ outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+ return 0;
+}
+#endif
+
+static struct isa_driver htcpen_isa_driver = {
+ .probe = htcpen_isa_probe,
+ .remove = __devexit_p(htcpen_isa_remove),
+#ifdef CONFIG_PM
+ .suspend = htcpen_isa_suspend,
+ .resume = htcpen_isa_resume,
+#endif
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "htcpen",
+ }
+};
+
+static struct dmi_system_id __initdata htcshift_dmi_table[] = {
+ {
+ .ident = "Shift",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "High Tech Computer Corp"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Shift"),
+ },
+ },
+ { }
+};
+
+static int __init htcpen_isa_init(void)
+{
+ if (!dmi_check_system(htcshift_dmi_table))
+ return -ENODEV;
+
+ return isa_register_driver(&htcpen_isa_driver, 1);
+}
+
+static void __exit htcpen_isa_exit(void)
+{
+ isa_unregister_driver(&htcpen_isa_driver);
+}
+
+module_init(htcpen_isa_init);
+module_exit(htcpen_isa_exit);
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
new file mode 100644
index 00000000000..192ade0a0fb
--- /dev/null
+++ b/drivers/input/touchscreen/inexio.c
@@ -0,0 +1,207 @@
+/*
+ * iNexio serial touchscreen driver
+ *
+ * Copyright (c) 2008 Richard Lemon
+ * Based on the mtouch driver (c) Vojtech Pavlik and Dan Streetman
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/*
+ * 2008/06/19 Richard Lemon <richard@codelemon.com>
+ * Copied mtouch.c and edited for iNexio protocol
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC "iNexio serial touchscreen driver"
+
+MODULE_AUTHOR("Richard Lemon <richard@codelemon.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define INEXIO_FORMAT_TOUCH_BIT 0x01
+#define INEXIO_FORMAT_LENGTH 5
+#define INEXIO_RESPONSE_BEGIN_BYTE 0x80
+
+/* todo: check specs for max length of all responses */
+#define INEXIO_MAX_LENGTH 16
+
+#define INEXIO_MIN_XC 0
+#define INEXIO_MAX_XC 0x3fff
+#define INEXIO_MIN_YC 0
+#define INEXIO_MAX_YC 0x3fff
+
+#define INEXIO_GET_XC(data) (((data[1])<<7) | data[2])
+#define INEXIO_GET_YC(data) (((data[3])<<7) | data[4])
+#define INEXIO_GET_TOUCHED(data) (INEXIO_FORMAT_TOUCH_BIT & data[0])
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct inexio {
+ struct input_dev *dev;
+ struct serio *serio;
+ int idx;
+ unsigned char data[INEXIO_MAX_LENGTH];
+ char phys[32];
+};
+
+static void inexio_process_data(struct inexio *pinexio)
+{
+ struct input_dev *dev = pinexio->dev;
+
+ if (INEXIO_FORMAT_LENGTH == ++pinexio->idx) {
+ input_report_abs(dev, ABS_X, INEXIO_GET_XC(pinexio->data));
+ input_report_abs(dev, ABS_Y, INEXIO_GET_YC(pinexio->data));
+ input_report_key(dev, BTN_TOUCH, INEXIO_GET_TOUCHED(pinexio->data));
+ input_sync(dev);
+
+ pinexio->idx = 0;
+ }
+}
+
+static irqreturn_t inexio_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags)
+{
+ struct inexio* pinexio = serio_get_drvdata(serio);
+
+ pinexio->data[pinexio->idx] = data;
+
+ if (INEXIO_RESPONSE_BEGIN_BYTE&pinexio->data[0])
+ inexio_process_data(pinexio);
+ else
+ printk(KERN_DEBUG "inexio.c: unknown/unsynchronized data from device, byte %x\n",pinexio->data[0]);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * inexio_disconnect() is the opposite of inexio_connect()
+ */
+
+static void inexio_disconnect(struct serio *serio)
+{
+ struct inexio* pinexio = serio_get_drvdata(serio);
+
+ input_get_device(pinexio->dev);
+ input_unregister_device(pinexio->dev);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ input_put_device(pinexio->dev);
+ kfree(pinexio);
+}
+
+/*
+ * inexio_connect() is the routine that is called when someone adds a
+ * new serio device that supports iNexio protocol and registers it as
+ * an input device. This is usually accomplished using inputattach.
+ */
+
+static int inexio_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct inexio *pinexio;
+ struct input_dev *input_dev;
+ int err;
+
+ pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!pinexio || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ pinexio->serio = serio;
+ pinexio->dev = input_dev;
+ snprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
+
+ input_dev->name = "iNexio Serial TouchScreen";
+ input_dev->phys = pinexio->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_INEXIO;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0001;
+ input_dev->dev.parent = &serio->dev;
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(pinexio->dev, ABS_X, INEXIO_MIN_XC, INEXIO_MAX_XC, 0, 0);
+ input_set_abs_params(pinexio->dev, ABS_Y, INEXIO_MIN_YC, INEXIO_MAX_YC, 0, 0);
+
+ serio_set_drvdata(serio, pinexio);
+
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail2;
+
+ err = input_register_device(pinexio->dev);
+ if (err)
+ goto fail3;
+
+ return 0;
+
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
+ kfree(pinexio);
+ return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id inexio_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_INEXIO,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, inexio_serio_ids);
+
+static struct serio_driver inexio_drv = {
+ .driver = {
+ .name = "inexio",
+ },
+ .description = DRIVER_DESC,
+ .id_table = inexio_serio_ids,
+ .interrupt = inexio_interrupt,
+ .connect = inexio_connect,
+ .disconnect = inexio_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init inexio_init(void)
+{
+ return serio_register_driver(&inexio_drv);
+}
+
+static void __exit inexio_exit(void)
+{
+ serio_unregister_driver(&inexio_drv);
+}
+
+module_init(inexio_init);
+module_exit(inexio_exit);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
new file mode 100644
index 00000000000..c1cd99d5898
--- /dev/null
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -0,0 +1,250 @@
+/*
+ * Touch Screen driver for Renesas MIGO-R Platform
+ *
+ * Copyright (c) 2008 Magnus Damm
+ * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
+ * Kenati Technologies Pvt Ltd.
+ *
+ * This file 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 file 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+
+#define EVENT_PENDOWN 1
+#define EVENT_REPEAT 2
+#define EVENT_PENUP 3
+
+struct migor_ts_priv {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct delayed_work work;
+ int irq;
+};
+
+static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11,
+ 0x01, 0x06, 0x07, };
+static const u_int8_t migor_ts_dis_seq[17] = { };
+
+static void migor_ts_poscheck(struct work_struct *work)
+{
+ struct migor_ts_priv *priv = container_of(work,
+ struct migor_ts_priv,
+ work.work);
+ unsigned short xpos, ypos;
+ unsigned char event;
+ u_int8_t buf[16];
+
+ memset(buf, 0, sizeof(buf));
+
+ /* Set Index 0 */
+ buf[0] = 0;
+ if (i2c_master_send(priv->client, buf, 1) != 1) {
+ dev_err(&priv->client->dev, "Unable to write i2c index\n");
+ goto out;
+ }
+
+ /* Now do Page Read */
+ if (i2c_master_recv(priv->client, buf, sizeof(buf)) != sizeof(buf)) {
+ dev_err(&priv->client->dev, "Unable to read i2c page\n");
+ goto out;
+ }
+
+ ypos = ((buf[9] & 0x03) << 8 | buf[8]);
+ xpos = ((buf[11] & 0x03) << 8 | buf[10]);
+ event = buf[12];
+
+ if (event == EVENT_PENDOWN || event == EVENT_REPEAT) {
+ input_report_key(priv->input, BTN_TOUCH, 1);
+ input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
+ input_report_abs(priv->input, ABS_Y, xpos);
+ input_sync(priv->input);
+ } else if (event == EVENT_PENUP) {
+ input_report_key(priv->input, BTN_TOUCH, 0);
+ input_sync(priv->input);
+ }
+ out:
+ enable_irq(priv->irq);
+}
+
+static irqreturn_t migor_ts_isr(int irq, void *dev_id)
+{
+ struct migor_ts_priv *priv = dev_id;
+
+ /* the touch screen controller chip is hooked up to the cpu
+ * using i2c and a single interrupt line. the interrupt line
+ * is pulled low whenever someone taps the screen. to deassert
+ * the interrupt line we need to acknowledge the interrupt by
+ * communicating with the controller over the slow i2c bus.
+ *
+ * we can't acknowledge from interrupt context since the i2c
+ * bus controller may sleep, so we just disable the interrupt
+ * here and handle the acknowledge using delayed work.
+ */
+
+ disable_irq_nosync(irq);
+ schedule_delayed_work(&priv->work, HZ / 20);
+
+ return IRQ_HANDLED;
+}
+
+
+static int migor_ts_open(struct input_dev *dev)
+{
+ struct migor_ts_priv *priv = input_get_drvdata(dev);
+ struct i2c_client *client = priv->client;
+ int count;
+
+ /* enable controller */
+ count = i2c_master_send(client, migor_ts_ena_seq,
+ sizeof(migor_ts_ena_seq));
+ if (count != sizeof(migor_ts_ena_seq)) {
+ dev_err(&client->dev, "Unable to enable touchscreen.\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void migor_ts_close(struct input_dev *dev)
+{
+ struct migor_ts_priv *priv = input_get_drvdata(dev);
+ struct i2c_client *client = priv->client;
+
+ disable_irq(priv->irq);
+
+ /* cancel pending work and wait for migor_ts_poscheck() to finish */
+ if (cancel_delayed_work_sync(&priv->work)) {
+ /*
+ * if migor_ts_poscheck was canceled we need to enable IRQ
+ * here to balance disable done in migor_ts_isr.
+ */
+ enable_irq(priv->irq);
+ }
+
+ /* disable controller */
+ i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
+
+ enable_irq(priv->irq);
+}
+
+static int migor_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *idp)
+{
+ struct migor_ts_priv *priv;
+ struct input_dev *input;
+ int error;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&client->dev, "failed to allocate driver data\n");
+ error = -ENOMEM;
+ goto err0;
+ }
+
+ dev_set_drvdata(&client->dev, priv);
+
+ input = input_allocate_device();
+ if (!input) {
+ dev_err(&client->dev, "Failed to allocate input device.\n");
+ error = -ENOMEM;
+ goto err1;
+ }
+
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input, ABS_X, 95, 955, 0, 0);
+ input_set_abs_params(input, ABS_Y, 85, 935, 0, 0);
+
+ input->name = client->driver_name;
+ input->id.bustype = BUS_I2C;
+ input->dev.parent = &client->dev;
+
+ input->open = migor_ts_open;
+ input->close = migor_ts_close;
+
+ input_set_drvdata(input, priv);
+
+ priv->client = client;
+ priv->input = input;
+ INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck);
+ priv->irq = client->irq;
+
+ error = input_register_device(input);
+ if (error)
+ goto err1;
+
+ error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
+ client->driver_name, priv);
+ if (error) {
+ dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+ goto err2;
+ }
+
+ return 0;
+
+ err2:
+ input_unregister_device(input);
+ input = NULL; /* so we dont try to free it below */
+ err1:
+ input_free_device(input);
+ kfree(priv);
+ err0:
+ dev_set_drvdata(&client->dev, NULL);
+ return error;
+}
+
+static int migor_ts_remove(struct i2c_client *client)
+{
+ struct migor_ts_priv *priv = dev_get_drvdata(&client->dev);
+
+ free_irq(priv->irq, priv);
+ input_unregister_device(priv->input);
+ kfree(priv);
+
+ dev_set_drvdata(&client->dev, NULL);
+
+ return 0;
+}
+
+static struct i2c_driver migor_ts_driver = {
+ .driver = {
+ .name = "migor_ts",
+ },
+ .probe = migor_ts_probe,
+ .remove = migor_ts_remove,
+};
+
+static int __init migor_ts_init(void)
+{
+ return i2c_add_driver(&migor_ts_driver);
+}
+
+static void __exit migor_ts_exit(void)
+{
+ i2c_del_driver(&migor_ts_driver);
+}
+
+MODULE_DESCRIPTION("MigoR Touchscreen driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
+
+module_init(migor_ts_init);
+module_exit(migor_ts_exit);
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
new file mode 100644
index 00000000000..d1297ba19da
--- /dev/null
+++ b/drivers/input/touchscreen/touchit213.c
@@ -0,0 +1,234 @@
+/*
+ * Sahara TouchIT-213 serial touchscreen driver
+ *
+ * Copyright (c) 2007-2008 Claudio Nieder <private@claudio.ch>
+ *
+ * Based on Touchright driver (drivers/input/touchscreen/touchright.c)
+ * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2004 Vojtech Pavlik
+ * and Dan Streetman <ddstreet@ieee.org>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC "Sahara TouchIT-213 serial touchscreen driver"
+
+MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+/*
+ * Data is received through COM1 at 9600bit/s,8bit,no parity in packets
+ * of 5 byte each.
+ *
+ * +--------+ +--------+ +--------+ +--------+ +--------+
+ * |1000000p| |0xxxxxxx| |0xxxxxxx| |0yyyyyyy| |0yyyyyyy|
+ * +--------+ +--------+ +--------+ +--------+ +--------+
+ * MSB LSB MSB LSB
+ *
+ * The value of p is 1 as long as the screen is touched and 0 when
+ * reporting the location where touching stopped, e.g. where the pen was
+ * lifted from the screen.
+ *
+ * When holding the screen in landscape mode as the BIOS text output is
+ * presented, x is the horizontal axis with values growing from left to
+ * right and y is the vertical axis with values growing from top to
+ * bottom.
+ *
+ * When holding the screen in portrait mode with the Sahara logo in its
+ * correct position, x ist the vertical axis with values growing from
+ * top to bottom and y is the horizontal axis with values growing from
+ * right to left.
+ */
+
+#define T213_FORMAT_TOUCH_BIT 0x01
+#define T213_FORMAT_STATUS_BYTE 0x80
+#define T213_FORMAT_STATUS_MASK ~T213_FORMAT_TOUCH_BIT
+
+/*
+ * On my Sahara Touch-IT 213 I have observed x values from 0 to 0x7f0
+ * and y values from 0x1d to 0x7e9, so the actual measurement is
+ * probably done with an 11 bit precision.
+ */
+#define T213_MIN_XC 0
+#define T213_MAX_XC 0x07ff
+#define T213_MIN_YC 0
+#define T213_MAX_YC 0x07ff
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct touchit213 {
+ struct input_dev *dev;
+ struct serio *serio;
+ int idx;
+ unsigned char csum;
+ unsigned char data[5];
+ char phys[32];
+};
+
+static irqreturn_t touchit213_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags)
+{
+ struct touchit213 *touchit213 = serio_get_drvdata(serio);
+ struct input_dev *dev = touchit213->dev;
+
+ touchit213->data[touchit213->idx] = data;
+
+ switch (touchit213->idx++) {
+ case 0:
+ if ((touchit213->data[0] & T213_FORMAT_STATUS_MASK) !=
+ T213_FORMAT_STATUS_BYTE) {
+ pr_debug("unsynchronized data: 0x%02x\n", data);
+ touchit213->idx = 0;
+ }
+ break;
+
+ case 4:
+ touchit213->idx = 0;
+ input_report_abs(dev, ABS_X,
+ (touchit213->data[1] << 7) | touchit213->data[2]);
+ input_report_abs(dev, ABS_Y,
+ (touchit213->data[3] << 7) | touchit213->data[4]);
+ input_report_key(dev, BTN_TOUCH,
+ touchit213->data[0] & T213_FORMAT_TOUCH_BIT);
+ input_sync(dev);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * touchit213_disconnect() is the opposite of touchit213_connect()
+ */
+
+static void touchit213_disconnect(struct serio *serio)
+{
+ struct touchit213 *touchit213 = serio_get_drvdata(serio);
+
+ input_get_device(touchit213->dev);
+ input_unregister_device(touchit213->dev);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ input_put_device(touchit213->dev);
+ kfree(touchit213);
+}
+
+/*
+ * touchit213_connect() is the routine that is called when someone adds a
+ * new serio device that supports the Touchright protocol and registers it as
+ * an input device.
+ */
+
+static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct touchit213 *touchit213;
+ struct input_dev *input_dev;
+ int err;
+
+ touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!touchit213 || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ touchit213->serio = serio;
+ touchit213->dev = input_dev;
+ snprintf(touchit213->phys, sizeof(touchit213->phys),
+ "%s/input0", serio->phys);
+
+ input_dev->name = "Sahara Touch-iT213 Serial TouchScreen";
+ input_dev->phys = touchit213->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_TOUCHIT213;
+ input_dev->id.product = 0;
+ input_dev->id.version = 0x0100;
+ input_dev->dev.parent = &serio->dev;
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(touchit213->dev, ABS_X,
+ T213_MIN_XC, T213_MAX_XC, 0, 0);
+ input_set_abs_params(touchit213->dev, ABS_Y,
+ T213_MIN_YC, T213_MAX_YC, 0, 0);
+
+ serio_set_drvdata(serio, touchit213);
+
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail2;
+
+ err = input_register_device(touchit213->dev);
+ if (err)
+ goto fail3;
+
+ return 0;
+
+ fail3: serio_close(serio);
+ fail2: serio_set_drvdata(serio, NULL);
+ fail1: input_free_device(input_dev);
+ kfree(touchit213);
+ return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id touchit213_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_TOUCHIT213,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, touchit213_serio_ids);
+
+static struct serio_driver touchit213_drv = {
+ .driver = {
+ .name = "touchit213",
+ },
+ .description = DRIVER_DESC,
+ .id_table = touchit213_serio_ids,
+ .interrupt = touchit213_interrupt,
+ .connect = touchit213_connect,
+ .disconnect = touchit213_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init touchit213_init(void)
+{
+ return serio_register_driver(&touchit213_drv);
+}
+
+static void __exit touchit213_exit(void)
+{
+ serio_unregister_driver(&touchit213_drv);
+}
+
+module_init(touchit213_init);
+module_exit(touchit213_exit);
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 3a0a8ca5707..fdd645c214a 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -49,6 +49,7 @@
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
+#include <linux/hid.h>
#define DRIVER_VERSION "v0.6"
@@ -101,7 +102,7 @@ struct usbtouch_usb {
/* device types */
enum {
- DEVTPYE_DUMMY = -1,
+ DEVTYPE_IGNORE = -1,
DEVTYPE_EGALAX,
DEVTYPE_PANJIT,
DEVTYPE_3M,
@@ -115,8 +116,21 @@ enum {
DEVTYPE_GOTOP,
};
+#define USB_DEVICE_HID_CLASS(vend, prod) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
+ | USB_DEVICE_ID_MATCH_DEVICE, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
+ .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE
+
static struct usb_device_id usbtouch_devices[] = {
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
+ /* ignore the HID capable devices, handled by usbhid */
+ {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
+ {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
+
+ /* normal device IDs */
{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
@@ -262,7 +276,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
- __FUNCTION__, ret);
+ __func__, ret);
if (ret < 0)
return ret;
msleep(150);
@@ -273,7 +287,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
- __FUNCTION__, ret);
+ __func__, ret);
if (ret >= 0)
break;
if (ret != -EPIPE)
@@ -793,18 +807,18 @@ static void usbtouch_irq(struct urb *urb)
case -ETIME:
/* this urb is timing out */
dbg("%s - urb timed out - was the device unplugged?",
- __FUNCTION__);
+ __func__);
return;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ __func__, urb->status);
goto exit;
}
@@ -814,7 +828,7 @@ exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("%s - usb_submit_urb failed with result: %d",
- __FUNCTION__, retval);
+ __func__, retval);
}
static int usbtouch_open(struct input_dev *input)
@@ -857,6 +871,10 @@ static int usbtouch_probe(struct usb_interface *intf,
struct usbtouch_device_info *type;
int err = -ENOMEM;
+ /* some devices are ignored */
+ if (id->driver_info == DEVTYPE_IGNORE)
+ return -ENODEV;
+
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
@@ -883,7 +901,7 @@ static int usbtouch_probe(struct usb_interface *intf,
usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!usbtouch->irq) {
- dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+ dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
goto out_free_buffers;
}
@@ -939,14 +957,14 @@ static int usbtouch_probe(struct usb_interface *intf,
if (type->init) {
err = type->init(usbtouch);
if (err) {
- dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+ dbg("%s - type->init() failed, err: %d", __func__, err);
goto out_free_buffers;
}
}
err = input_register_device(usbtouch->input);
if (err) {
- dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+ dbg("%s - input_register_device failed, err: %d", __func__, err);
goto out_free_buffers;
}
@@ -966,12 +984,12 @@ static void usbtouch_disconnect(struct usb_interface *intf)
{
struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
- dbg("%s - called", __FUNCTION__);
+ dbg("%s - called", __func__);
if (!usbtouch)
return;
- dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+ dbg("%s - usbtouch is initialized, cleaning up", __func__);
usb_set_intfdata(intf, NULL);
usb_kill_urb(usbtouch->irq);
input_unregister_device(usbtouch->input);
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 0b6e4cfa6a2..4c5d85a249a 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -168,6 +168,18 @@ static void wm9712_phy_init(struct wm97xx *wm)
64000 / rpu);
}
+ /* WM9712 five wire */
+ if (five_wire) {
+ dig2 |= WM9712_45W;
+ dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
+
+ if (pil) {
+ dev_warn(wm->dev, "pressure measurement is not "
+ "supported in 5-wire mode\n");
+ pil = 0;
+ }
+ }
+
/* touchpanel pressure current*/
if (pil == 2) {
dig2 |= WM9712_PIL;
@@ -179,12 +191,6 @@ static void wm9712_phy_init(struct wm97xx *wm)
if (!pil)
pressure = 0;
- /* WM9712 five wire */
- if (five_wire) {
- dig2 |= WM9712_45W;
- dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
- }
-
/* polling mode sample settling delay */
if (delay < 0 || delay > 15) {
dev_dbg(wm->dev, "supplied delay out of range.");
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 8a35029caca..871b0cbca5e 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty)
#endif
}
-static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
{
#ifdef _DEBUG_TTYFUNCS
printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
#endif
+ return 0;
}
static void capinc_tty_flush_buffer(struct tty_struct *tty)
@@ -1552,7 +1553,8 @@ static int __init capi_init(void)
return PTR_ERR(capi_class);
}
- device_create(capi_class, NULL, MKDEV(capi_major, 0), "capi");
+ device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
+ "capi");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 091deb9d1c4..c2bd97d2927 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -575,7 +575,8 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
else
skb = iraw_encode(skb, HW_HDR_LEN, 0);
if (!skb) {
- err("unable to allocate memory for encoding!\n");
+ dev_err(bcs->cs->dev,
+ "unable to allocate memory for encoding!\n");
return -ENOMEM;
}
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 5255b5e20e1..3f11910c7cc 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -1050,10 +1050,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
}
/* retrieve block of data to send */
- ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
- ifd->length);
- if (ifd->offset < 0) {
- if (ifd->offset == -EBUSY) {
+ rc = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+ if (rc < 0) {
+ if (rc == -EBUSY) {
gig_dbg(DEBUG_ISO,
"%s: buffer busy at frame %d",
__func__, nframe);
@@ -1062,11 +1061,12 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
} else {
dev_err(ucx->bcs->cs->dev,
"%s: buffer error %d at frame %d\n",
- __func__, ifd->offset, nframe);
- return ifd->offset;
+ __func__, rc, nframe);
+ return rc;
}
break;
}
+ ifd->offset = rc;
ucx->limit = ubc->isooutbuf->nextread;
ifd->status = 0;
ifd->actual_length = 0;
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 827c32c1679..9d3ce7718e5 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -287,7 +287,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
tail = cs->ev_tail;
next = (tail + 1) % MAX_EVENTS;
if (unlikely(next == cs->ev_head))
- err("event queue full");
+ dev_err(cs->dev, "event queue full\n");
else {
event = cs->events + tail;
event->type = type;
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index f365993161f..00375295499 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -106,7 +106,6 @@ enum debuglevel {
#undef err
#undef info
#undef warn
-#undef notice
#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
format "\n" , ## arg)
@@ -114,8 +113,6 @@ enum debuglevel {
format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
format "\n" , ## arg)
-#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
- format "\n" , ## arg)
#ifdef CONFIG_GIGASET_DEBUG
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 9e089f06a94..3c127a8cbaf 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -46,7 +46,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
return -ENODEV;
}
if (channel < 0 || channel >= cs->channels) {
- err("%s: invalid channel ID (%d)", __func__, channel);
+ dev_err(cs->dev, "%s: invalid channel ID (%d)\n",
+ __func__, channel);
return -ENODEV;
}
bcs = &cs->bcs[channel];
@@ -58,11 +59,13 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
if (!len) {
if (ack)
- notice("%s: not ACKing empty packet", __func__);
+ dev_notice(cs->dev, "%s: not ACKing empty packet\n",
+ __func__);
return 0;
}
if (len > MAX_BUF_SIZE) {
- err("%s: packet too large (%d bytes)", __func__, len);
+ dev_err(cs->dev, "%s: packet too large (%d bytes)\n",
+ __func__, len);
return -EINVAL;
}
@@ -116,8 +119,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
gigaset_debugdrivers();
if (!cs) {
- warn("LL tried to access unknown device with nr. %d",
- cntrl->driver);
+ err("%s: invalid driver ID (%d)", __func__, cntrl->driver);
return -ENODEV;
}
@@ -126,7 +128,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
cntrl->driver, cntrl->arg);
- warn("ISDN_CMD_IOCTL is not supported.");
+ dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
return -EINVAL;
case ISDN_CMD_DIAL:
@@ -138,22 +140,23 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->parm.setup.si1, cntrl->parm.setup.si2);
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_DIAL: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_DIAL: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
bcs = cs->bcs + cntrl->arg;
if (!gigaset_get_channel(bcs)) {
- err("ISDN_CMD_DIAL: channel not free");
+ dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
return -EBUSY;
}
sp = kmalloc(sizeof *sp, GFP_ATOMIC);
if (!sp) {
gigaset_free_channel(bcs);
- err("ISDN_CMD_DIAL: out of memory");
+ dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
return -ENOMEM;
}
*sp = cntrl->parm.setup;
@@ -173,8 +176,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
@@ -196,8 +200,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
(int) cntrl->arg);
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_HANGUP: invalid channel (%u)",
- (unsigned) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_HANGUP: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
@@ -224,8 +229,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("ISDN_CMD_SETL2: invalid channel (%u)",
- (unsigned) cntrl->arg & 0xff);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL2: invalid channel (%d)\n",
+ (int) cntrl->arg & 0xff);
return -EINVAL;
}
@@ -244,14 +250,16 @@ static int command_from_LL(isdn_ctrl *cntrl)
cntrl->arg & 0xff, (cntrl->arg >> 8));
if ((cntrl->arg & 0xff) >= cs->channels) {
- err("ISDN_CMD_SETL3: invalid channel (%u)",
- (unsigned) cntrl->arg & 0xff);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL3: invalid channel (%d)\n",
+ (int) cntrl->arg & 0xff);
return -EINVAL;
}
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
- err("ISDN_CMD_SETL3: invalid protocol %lu",
- cntrl->arg >> 8);
+ dev_err(cs->dev,
+ "ISDN_CMD_SETL3: invalid protocol %lu\n",
+ cntrl->arg >> 8);
return -EINVAL;
}
@@ -262,8 +270,9 @@ static int command_from_LL(isdn_ctrl *cntrl)
case ISDN_CMD_ALERT:
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
if (cntrl->arg >= cs->channels) {
- err("ISDN_CMD_ALERT: invalid channel (%d)",
- (int) cntrl->arg);
+ dev_err(cs->dev,
+ "ISDN_CMD_ALERT: invalid channel (%d)\n",
+ (int) cntrl->arg);
return -EINVAL;
}
//bcs = cs->bcs + cntrl->arg;
@@ -295,7 +304,8 @@ static int command_from_LL(isdn_ctrl *cntrl)
gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
break;
default:
- err("unknown command %d from LL", cntrl->command);
+ dev_err(cs->dev, "unknown command %d from LL\n",
+ cntrl->command);
return -EINVAL;
}
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index af195b07c19..521951a898e 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -197,7 +197,7 @@ static void if_close(struct tty_struct *tty, struct file *filp)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
if (!--cs->open_count) {
spin_lock_irqsave(&cs->lock, flags);
@@ -232,7 +232,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
retval = 0;
switch (cmd) {
@@ -364,9 +364,9 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -398,9 +398,9 @@ static int if_write_room(struct tty_struct *tty)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -430,9 +430,9 @@ static int if_chars_in_buffer(struct tty_struct *tty)
return -ERESTARTSYS; // FIXME -EINTR?
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
- warn("can't write to unlocked device");
+ dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else if (!cs->connected) {
gig_dbg(DEBUG_ANY, "can't write to unplugged device");
@@ -460,7 +460,7 @@ static void if_throttle(struct tty_struct *tty)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
//FIXME
}
@@ -483,7 +483,7 @@ static void if_unthrottle(struct tty_struct *tty)
mutex_lock(&cs->mutex);
if (!cs->open_count)
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
else {
//FIXME
}
@@ -510,7 +510,7 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
mutex_lock(&cs->mutex);
if (!cs->open_count) {
- warn("%s: device not opened", __func__);
+ dev_warn(cs->dev, "%s: device not opened\n", __func__);
goto out;
}
@@ -623,7 +623,8 @@ void gigaset_if_init(struct cardstate *cs)
if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
else {
- warn("could not register device to the tty subsystem");
+ dev_warn(cs->dev,
+ "could not register device to the tty subsystem\n");
cs->tty_dev = NULL;
}
mutex_unlock(&cs->mutex);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 77d20ab0cd4..4661830a49d 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -498,8 +498,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
if (status) {
ucs->busy = 0;
- err("could not submit urb (error %d)\n",
- -status);
+ dev_err(cs->dev,
+ "could not submit urb (error %d)\n",
+ -status);
cb->len = 0; /* skip urb => remove cb+wakeup
in next loop cycle */
}
@@ -670,7 +671,7 @@ static int write_modem(struct cardstate *cs)
spin_unlock_irqrestore(&cs->lock, flags);
if (ret) {
- err("could not submit urb (error %d)\n", -ret);
+ dev_err(cs->dev, "could not submit urb (error %d)\n", -ret);
ucs->busy = 0;
}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 86a369bc57d..9556262dda5 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -103,6 +103,14 @@ config LEDS_HP6XX
This option enables led support for the handheld
HP Jornada 620/660/680/690.
+config LEDS_PCA9532
+ tristate "LED driver for PCA9532 dimmer"
+ depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL
+ help
+ This option enables support for NXP pca9532
+ led controller. It is generally only usefull
+ as a platform driver
+
config LEDS_GPIO
tristate "LED Support for GPIO connected LEDs"
depends on LEDS_CLASS && GENERIC_GPIO
@@ -147,6 +155,14 @@ config LEDS_CLEVO_MAIL
To compile this driver as a module, choose M here: the
module will be called leds-clevo-mail.
+config LEDS_PCA955X
+ tristate "LED Support for PCA955x I2C chips"
+ depends on LEDS_CLASS && I2C
+ help
+ This option enables support for LEDs connected to PCA955x
+ LED driver chips accessed via the I2C bus. Supported
+ devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+
comment "LED Triggers"
config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 973d626f5f4..ff7982b4456 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,11 +16,13 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
+obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
+obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 0f242b3f09b..f910eaffe3a 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -111,16 +111,17 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
flags);
if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev);
+ led_cdev->trigger = NULL;
led_set_brightness(led_cdev, LED_OFF);
}
if (trigger) {
write_lock_irqsave(&trigger->leddev_list_lock, flags);
list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
+ led_cdev->trigger = trigger;
if (trigger->activate)
trigger->activate(led_cdev);
}
- led_cdev->trigger = trigger;
}
EXPORT_SYMBOL_GPL(led_trigger_set);
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 28db6c1444e..52297c3ab24 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -37,7 +37,7 @@ static int __init pwmled_probe(struct platform_device *pdev)
{
const struct gpio_led_platform_data *pdata;
struct pwmled *leds;
- unsigned i;
+ int i;
int status;
pdata = pdev->dev.platform_data;
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
index bcec4223038..73c70502168 100644
--- a/drivers/leds/leds-h1940.c
+++ b/drivers/leds/leds-h1940.c
@@ -23,7 +23,8 @@
/*
* Green led.
*/
-void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_greenled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
switch (value) {
case LED_HALF:
@@ -52,7 +53,8 @@ static struct led_classdev h1940_greenled = {
/*
* Red led.
*/
-void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_redled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
switch (value) {
case LED_HALF:
@@ -82,7 +84,8 @@ static struct led_classdev h1940_redled = {
* Blue led.
* (it can only be blue flashing led)
*/
-void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
+static void h1940_blueled_set(struct led_classdev *led_dev,
+ enum led_brightness value)
{
if (value) {
/* flashing Blue */
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
new file mode 100644
index 00000000000..4064d4f6b33
--- /dev/null
+++ b/drivers/leds/leds-pca9532.c
@@ -0,0 +1,337 @@
+/*
+ * pca9532.c - 16-bit Led dimmer
+ *
+ * Copyright (C) 2008 Riku Voipio <riku.voipio@movial.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * Datasheet: http://www.nxp.com/acrobat/datasheets/PCA9532_3.pdf
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/leds-pca9532.h>
+
+static const unsigned short normal_i2c[] = { /*0x60,*/ I2C_CLIENT_END};
+I2C_CLIENT_INSMOD_1(pca9532);
+
+#define PCA9532_REG_PSC(i) (0x2+(i)*2)
+#define PCA9532_REG_PWM(i) (0x3+(i)*2)
+#define PCA9532_REG_LS0 0x6
+#define LED_REG(led) ((led>>2)+PCA9532_REG_LS0)
+#define LED_NUM(led) (led & 0x3)
+
+#define ldev_to_led(c) container_of(c, struct pca9532_led, ldev)
+
+struct pca9532_data {
+ struct i2c_client *client;
+ struct pca9532_led leds[16];
+ struct mutex update_lock;
+ struct input_dev *idev;
+ u8 pwm[2];
+ u8 psc[2];
+};
+
+static int pca9532_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int pca9532_remove(struct i2c_client *client);
+
+static const struct i2c_device_id pca9532_id[] = {
+ { "pca9532", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9532_id);
+
+static struct i2c_driver pca9532_driver = {
+ .driver = {
+ .name = "pca9532",
+ },
+ .probe = pca9532_probe,
+ .remove = pca9532_remove,
+ .id_table = pca9532_id,
+};
+
+/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly,
+ * the clever Thecus people are using one pwm to drive the beeper. So,
+ * as a compromise we average one pwm to the values requested by all
+ * leds that are not ON/OFF.
+ * */
+static int pca9532_setpwm(struct i2c_client *client, int pwm, int blink,
+ enum led_brightness value)
+{
+ int a = 0, b = 0, i = 0;
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ for (i = 0; i < 16; i++) {
+ if (data->leds[i].type == PCA9532_TYPE_LED &&
+ data->leds[i].state == PCA9532_PWM0+pwm) {
+ a++;
+ b += data->leds[i].ldev.brightness;
+ }
+ }
+ if (a == 0) {
+ dev_err(&client->dev,
+ "fear of division by zero %d/%d, wanted %d\n",
+ b, a, value);
+ return -EINVAL;
+ }
+ b = b/a;
+ if (b > 0xFF)
+ return -EINVAL;
+ mutex_lock(&data->update_lock);
+ data->pwm[pwm] = b;
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
+ data->pwm[pwm]);
+ data->psc[pwm] = blink;
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
+ data->psc[pwm]);
+ mutex_unlock(&data->update_lock);
+ return 0;
+}
+
+/* Set LED routing */
+static void pca9532_setled(struct pca9532_led *led)
+{
+ struct i2c_client *client = led->client;
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ char reg;
+
+ mutex_lock(&data->update_lock);
+ reg = i2c_smbus_read_byte_data(client, LED_REG(led->id));
+ /* zero led bits */
+ reg = reg & ~(0x3<<LED_NUM(led->id)*2);
+ /* set the new value */
+ reg = reg | (led->state << LED_NUM(led->id)*2);
+ i2c_smbus_write_byte_data(client, LED_REG(led->id), reg);
+ mutex_unlock(&data->update_lock);
+}
+
+static void pca9532_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ int err = 0;
+ struct pca9532_led *led = ldev_to_led(led_cdev);
+
+ if (value == LED_OFF)
+ led->state = PCA9532_OFF;
+ else if (value == LED_FULL)
+ led->state = PCA9532_ON;
+ else {
+ led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
+ err = pca9532_setpwm(led->client, 0, 0, value);
+ if (err)
+ return; /* XXX: led api doesn't allow error code? */
+ }
+ pca9532_setled(led);
+}
+
+static int pca9532_set_blink(struct led_classdev *led_cdev,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ struct pca9532_led *led = ldev_to_led(led_cdev);
+ struct i2c_client *client = led->client;
+ int psc;
+
+ if (*delay_on == 0 && *delay_off == 0) {
+ /* led subsystem ask us for a blink rate */
+ *delay_on = 1000;
+ *delay_off = 1000;
+ }
+ if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
+ return -EINVAL;
+
+ /* Thecus specific: only use PSC/PWM 0 */
+ psc = (*delay_on * 152-1)/1000;
+ return pca9532_setpwm(client, 0, psc, led_cdev->brightness);
+}
+
+int pca9532_event(struct input_dev *dev, unsigned int type, unsigned int code,
+ int value)
+{
+ struct pca9532_data *data = input_get_drvdata(dev);
+
+ if (type != EV_SND && (code != SND_BELL || code != SND_TONE))
+ return -1;
+
+ /* XXX: allow different kind of beeps with psc/pwm modifications */
+ if (value > 1 && value < 32767)
+ data->pwm[1] = 127;
+ else
+ data->pwm[1] = 0;
+
+ dev_info(&dev->dev, "setting beep to %d \n", data->pwm[1]);
+ mutex_lock(&data->update_lock);
+ i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
+ data->pwm[1]);
+ mutex_unlock(&data->update_lock);
+
+ return 0;
+}
+
+static int pca9532_configure(struct i2c_client *client,
+ struct pca9532_data *data, struct pca9532_platform_data *pdata)
+{
+ int i, err = 0;
+
+ for (i = 0; i < 2; i++) {
+ data->pwm[i] = pdata->pwm[i];
+ data->psc[i] = pdata->psc[i];
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(i),
+ data->pwm[i]);
+ i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(i),
+ data->psc[i]);
+ }
+
+ for (i = 0; i < 16; i++) {
+ struct pca9532_led *led = &data->leds[i];
+ struct pca9532_led *pled = &pdata->leds[i];
+ led->client = client;
+ led->id = i;
+ led->type = pled->type;
+ switch (led->type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led->state = pled->state;
+ led->name = pled->name;
+ led->ldev.name = led->name;
+ led->ldev.brightness = LED_OFF;
+ led->ldev.brightness_set = pca9532_set_brightness;
+ led->ldev.blink_set = pca9532_set_blink;
+ if (led_classdev_register(&client->dev,
+ &led->ldev) < 0) {
+ dev_err(&client->dev,
+ "couldn't register LED %s\n",
+ led->name);
+ goto exit;
+ }
+ pca9532_setled(led);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ BUG_ON(data->idev);
+ led->state = PCA9532_PWM1;
+ pca9532_setled(led);
+ data->idev = input_allocate_device();
+ if (data->idev == NULL) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ data->idev->name = pled->name;
+ data->idev->phys = "i2c/pca9532";
+ data->idev->id.bustype = BUS_HOST;
+ data->idev->id.vendor = 0x001f;
+ data->idev->id.product = 0x0001;
+ data->idev->id.version = 0x0100;
+ data->idev->evbit[0] = BIT_MASK(EV_SND);
+ data->idev->sndbit[0] = BIT_MASK(SND_BELL) |
+ BIT_MASK(SND_TONE);
+ data->idev->event = pca9532_event;
+ input_set_drvdata(data->idev, data);
+ err = input_register_device(data->idev);
+ if (err) {
+ input_free_device(data->idev);
+ data->idev = NULL;
+ goto exit;
+ }
+ break;
+ }
+ }
+ return 0;
+
+exit:
+ if (i > 0)
+ for (i = i - 1; i >= 0; i--)
+ switch (data->leds[i].type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led_classdev_unregister(&data->leds[i].ldev);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ if (data->idev != NULL) {
+ input_unregister_device(data->idev);
+ input_free_device(data->idev);
+ data->idev = NULL;
+ }
+ break;
+ }
+
+ return err;
+
+}
+
+static int pca9532_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct pca9532_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ dev_info(&client->dev, "setting platform data\n");
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ if (pca9532_pdata == NULL)
+ return -EIO;
+
+ pca9532_configure(client, data, pca9532_pdata);
+ return 0;
+
+}
+
+static int pca9532_remove(struct i2c_client *client)
+{
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ int i;
+ for (i = 0; i < 16; i++)
+ switch (data->leds[i].type) {
+ case PCA9532_TYPE_NONE:
+ break;
+ case PCA9532_TYPE_LED:
+ led_classdev_unregister(&data->leds[i].ldev);
+ break;
+ case PCA9532_TYPE_N2100_BEEP:
+ if (data->idev != NULL) {
+ input_unregister_device(data->idev);
+ input_free_device(data->idev);
+ data->idev = NULL;
+ }
+ break;
+ }
+
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static int __init pca9532_init(void)
+{
+ return i2c_add_driver(&pca9532_driver);
+}
+
+static void __exit pca9532_exit(void)
+{
+ i2c_del_driver(&pca9532_driver);
+}
+
+MODULE_AUTHOR("Riku Voipio <riku.voipio@movial.fi>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCA 9532 LED dimmer");
+
+module_init(pca9532_init);
+module_exit(pca9532_exit);
+
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
new file mode 100644
index 00000000000..146c0697286
--- /dev/null
+++ b/drivers/leds/leds-pca955x.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2007-2008 Extreme Engineering Solutions, Inc.
+ *
+ * Author: Nate Case <ncase@xes-inc.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * LED driver for various PCA955x I2C LED drivers
+ *
+ * Supported devices:
+ *
+ * Device Description 7-bit slave address
+ * ------ ----------- -------------------
+ * PCA9550 2-bit driver 0x60 .. 0x61
+ * PCA9551 8-bit driver 0x60 .. 0x67
+ * PCA9552 16-bit driver 0x60 .. 0x67
+ * PCA9553/01 4-bit driver 0x62
+ * PCA9553/02 4-bit driver 0x63
+ *
+ * Philips PCA955x LED driver chips follow a register map as shown below:
+ *
+ * Control Register Description
+ * ---------------- -----------
+ * 0x0 Input register 0
+ * ..
+ * NUM_INPUT_REGS - 1 Last Input register X
+ *
+ * NUM_INPUT_REGS Frequency prescaler 0
+ * NUM_INPUT_REGS + 1 PWM register 0
+ * NUM_INPUT_REGS + 2 Frequency prescaler 1
+ * NUM_INPUT_REGS + 3 PWM register 1
+ *
+ * NUM_INPUT_REGS + 4 LED selector 0
+ * NUM_INPUT_REGS + 4
+ * + NUM_LED_REGS - 1 Last LED selector
+ *
+ * where NUM_INPUT_REGS and NUM_LED_REGS vary depending on how many
+ * bits the chip supports.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define PCA955X_LS_LED_ON 0x0 /* Output LOW */
+#define PCA955X_LS_LED_OFF 0x1 /* Output HI-Z */
+#define PCA955X_LS_BLINK0 0x2 /* Blink at PWM0 rate */
+#define PCA955X_LS_BLINK1 0x3 /* Blink at PWM1 rate */
+
+enum pca955x_type {
+ pca9550,
+ pca9551,
+ pca9552,
+ pca9553,
+};
+
+struct pca955x_chipdef {
+ int bits;
+ u8 slv_addr; /* 7-bit slave address mask */
+ int slv_addr_shift; /* Number of bits to ignore */
+};
+
+static struct pca955x_chipdef pca955x_chipdefs[] = {
+ [pca9550] = {
+ .bits = 2,
+ .slv_addr = /* 110000x */ 0x60,
+ .slv_addr_shift = 1,
+ },
+ [pca9551] = {
+ .bits = 8,
+ .slv_addr = /* 1100xxx */ 0x60,
+ .slv_addr_shift = 3,
+ },
+ [pca9552] = {
+ .bits = 16,
+ .slv_addr = /* 1100xxx */ 0x60,
+ .slv_addr_shift = 3,
+ },
+ [pca9553] = {
+ .bits = 4,
+ .slv_addr = /* 110001x */ 0x62,
+ .slv_addr_shift = 1,
+ },
+};
+
+static const struct i2c_device_id pca955x_id[] = {
+ { "pca9550", pca9550 },
+ { "pca9551", pca9551 },
+ { "pca9552", pca9552 },
+ { "pca9553", pca9553 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pca955x_id);
+
+struct pca955x_led {
+ struct pca955x_chipdef *chipdef;
+ struct i2c_client *client;
+ struct work_struct work;
+ spinlock_t lock;
+ enum led_brightness brightness;
+ struct led_classdev led_cdev;
+ int led_num; /* 0 .. 15 potentially */
+ char name[32];
+};
+
+/* 8 bits per input register */
+static inline int pca95xx_num_input_regs(int bits)
+{
+ return (bits + 7) / 8;
+}
+
+/* 4 bits per LED selector register */
+static inline int pca95xx_num_led_regs(int bits)
+{
+ return (bits + 3) / 4;
+}
+
+/*
+ * Return an LED selector register value based on an existing one, with
+ * the appropriate 2-bit state value set for the given LED number (0-3).
+ */
+static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
+{
+ return (oldval & (~(0x3 << (led_num << 1)))) |
+ ((state & 0x3) << (led_num << 1));
+}
+
+/*
+ * Write to frequency prescaler register, used to program the
+ * period of the PWM output. period = (PSCx + 1) / 38
+ */
+static void pca955x_write_psc(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
+ val);
+}
+
+/*
+ * Write to PWM register, which determines the duty cycle of the
+ * output. LED is OFF when the count is less than the value of this
+ * register, and ON when it is greater. If PWMx == 0, LED is always OFF.
+ *
+ * Duty cycle is (256 - PWMx) / 256
+ */
+static void pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
+ val);
+}
+
+/*
+ * Write to LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static void pca955x_write_ls(struct i2c_client *client, int n, u8 val)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ i2c_smbus_write_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
+ val);
+}
+
+/*
+ * Read the LED selector register, which determines the source that
+ * drives the LED output.
+ */
+static u8 pca955x_read_ls(struct i2c_client *client, int n)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+
+ return (u8) i2c_smbus_read_byte_data(client,
+ pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
+}
+
+static void pca955x_led_work(struct work_struct *work)
+{
+ struct pca955x_led *pca955x;
+ u8 ls;
+ int chip_ls; /* which LSx to use (0-3 potentially) */
+ int ls_led; /* which set of bits within LSx to use (0-3) */
+
+ pca955x = container_of(work, struct pca955x_led, work);
+ chip_ls = pca955x->led_num / 4;
+ ls_led = pca955x->led_num % 4;
+
+ ls = pca955x_read_ls(pca955x->client, chip_ls);
+
+ switch (pca955x->brightness) {
+ case LED_FULL:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
+ break;
+ case LED_OFF:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
+ break;
+ case LED_HALF:
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK0);
+ break;
+ default:
+ /*
+ * Use PWM1 for all other values. This has the unwanted
+ * side effect of making all LEDs on the chip share the
+ * same brightness level if set to a value other than
+ * OFF, HALF, or FULL. But, this is probably better than
+ * just turning off for all other values.
+ */
+ pca955x_write_pwm(pca955x->client, 1, 255-pca955x->brightness);
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
+ break;
+ }
+
+ pca955x_write_ls(pca955x->client, chip_ls, ls);
+}
+
+void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
+{
+ struct pca955x_led *pca955x;
+
+ pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
+
+ spin_lock(&pca955x->lock);
+ pca955x->brightness = value;
+
+ /*
+ * Must use workqueue for the actual I/O since I2C operations
+ * can sleep.
+ */
+ schedule_work(&pca955x->work);
+
+ spin_unlock(&pca955x->lock);
+}
+
+static int __devinit pca955x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pca955x_led *pca955x;
+ int i;
+ int err = -ENODEV;
+ struct pca955x_chipdef *chip;
+ struct i2c_adapter *adapter;
+ struct led_platform_data *pdata;
+
+ chip = &pca955x_chipdefs[id->driver_data];
+ adapter = to_i2c_adapter(client->dev.parent);
+ pdata = client->dev.platform_data;
+
+ /* Make sure the slave address / chip type combo given is possible */
+ if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
+ chip->slv_addr) {
+ dev_err(&client->dev, "invalid slave address %02x\n",
+ client->addr);
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "leds-pca955x: Using %s %d-bit LED driver at "
+ "slave address 0x%02x\n",
+ id->name, chip->bits, client->addr);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return -EIO;
+
+ if (pdata) {
+ if (pdata->num_leds != chip->bits) {
+ dev_err(&client->dev, "board info claims %d LEDs"
+ " on a %d-bit chip\n",
+ pdata->num_leds, chip->bits);
+ return -ENODEV;
+ }
+ }
+
+ for (i = 0; i < chip->bits; i++) {
+ pca955x = kzalloc(sizeof(struct pca955x_led), GFP_KERNEL);
+ if (!pca955x) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pca955x->chipdef = chip;
+ pca955x->client = client;
+ pca955x->led_num = i;
+ /* Platform data can specify LED names and default triggers */
+ if (pdata) {
+ if (pdata->leds[i].name)
+ snprintf(pca955x->name, 32, "pca955x:%s",
+ pdata->leds[i].name);
+ if (pdata->leds[i].default_trigger)
+ pca955x->led_cdev.default_trigger =
+ pdata->leds[i].default_trigger;
+ } else {
+ snprintf(pca955x->name, 32, "pca955x:%d", i);
+ }
+ spin_lock_init(&pca955x->lock);
+
+ pca955x->led_cdev.name = pca955x->name;
+ pca955x->led_cdev.brightness_set =
+ pca955x_led_set;
+
+ /*
+ * Client data is a pointer to the _first_ pca955x_led
+ * struct
+ */
+ if (i == 0)
+ i2c_set_clientdata(client, pca955x);
+
+ INIT_WORK(&(pca955x->work), pca955x_led_work);
+
+ led_classdev_register(&client->dev, &(pca955x->led_cdev));
+ }
+
+ /* Turn off LEDs */
+ for (i = 0; i < pca95xx_num_led_regs(chip->bits); i++)
+ pca955x_write_ls(client, i, 0x55);
+
+ /* PWM0 is used for half brightness or 50% duty cycle */
+ pca955x_write_pwm(client, 0, 255-LED_HALF);
+
+ /* PWM1 is used for variable brightness, default to OFF */
+ pca955x_write_pwm(client, 1, 0);
+
+ /* Set to fast frequency so we do not see flashing */
+ pca955x_write_psc(client, 0, 0);
+ pca955x_write_psc(client, 1, 0);
+
+ return 0;
+exit:
+ return err;
+}
+
+static int __devexit pca955x_remove(struct i2c_client *client)
+{
+ struct pca955x_led *pca955x = i2c_get_clientdata(client);
+ int leds = pca955x->chipdef->bits;
+ int i;
+
+ for (i = 0; i < leds; i++) {
+ led_classdev_unregister(&(pca955x->led_cdev));
+ cancel_work_sync(&(pca955x->work));
+ kfree(pca955x);
+ pca955x = pca955x + 1;
+ }
+
+ return 0;
+}
+
+static struct i2c_driver pca955x_driver = {
+ .driver = {
+ .name = "leds-pca955x",
+ .owner = THIS_MODULE,
+ },
+ .probe = pca955x_probe,
+ .remove = __devexit_p(pca955x_remove),
+ .id_table = pca955x_id,
+};
+
+static int __init pca955x_leds_init(void)
+{
+ return i2c_add_driver(&pca955x_driver);
+}
+
+static void __exit pca955x_leds_exit(void)
+{
+ i2c_del_driver(&pca955x_driver);
+}
+
+module_init(pca955x_leds_init);
+module_exit(pca955x_leds_exit);
+
+MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
+MODULE_DESCRIPTION("PCA955x LED driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index e5d446804d3..cae52485208 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -862,7 +862,8 @@ adbdev_init(void)
adb_dev_class = class_create(THIS_MODULE, "adb");
if (IS_ERR(adb_dev_class))
return;
- device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb");
+ device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
+ "adb");
platform_device_register(&adb_pfdev);
platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 59ea520a5d7..5396c67ba0a 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -219,11 +219,13 @@ struct adbhid {
int flags;
};
-#define FLAG_FN_KEY_PRESSED 0x00000001
-#define FLAG_POWER_FROM_FN 0x00000002
-#define FLAG_EMU_FWDEL_DOWN 0x00000004
-#define FLAG_CAPSLOCK_TRANSLATE 0x00000008
-#define FLAG_CAPSLOCK_DOWN 0x00000010
+#define FLAG_FN_KEY_PRESSED 0x00000001
+#define FLAG_POWER_FROM_FN 0x00000002
+#define FLAG_EMU_FWDEL_DOWN 0x00000004
+#define FLAG_CAPSLOCK_TRANSLATE 0x00000008
+#define FLAG_CAPSLOCK_DOWN 0x00000010
+#define FLAG_CAPSLOCK_IGNORE_NEXT 0x00000020
+#define FLAG_POWER_KEY_PRESSED 0x00000040
static struct adbhid *adbhid[16];
@@ -291,11 +293,20 @@ adbhid_input_keycode(int id, int scancode, int repeat)
if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
/* Key pressed, turning on the CapsLock LED.
* The next 0xff will be interpreted as a release. */
- ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
+ if (ahid->flags & FLAG_CAPSLOCK_IGNORE_NEXT) {
+ /* Throw away this key event if it happens
+ * just after resume. */
+ ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT;
+ return;
+ } else {
+ ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
| FLAG_CAPSLOCK_DOWN;
- } else if (scancode == 0xff) {
+ }
+ } else if (scancode == 0xff &&
+ !(ahid->flags & FLAG_POWER_KEY_PRESSED)) {
/* Scancode 0xff usually signifies that the capslock
- * key was either pressed or released. */
+ * key was either pressed or released, or that the
+ * power button was released. */
if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {
keycode = ADB_KEY_CAPSLOCK;
if (ahid->flags & FLAG_CAPSLOCK_DOWN) {
@@ -309,7 +320,7 @@ adbhid_input_keycode(int id, int scancode, int repeat)
}
} else {
printk(KERN_INFO "Spurious caps lock event "
- "(scancode 0xff).");
+ "(scancode 0xff).\n");
}
}
}
@@ -336,6 +347,12 @@ adbhid_input_keycode(int id, int scancode, int repeat)
}
break;
case ADB_KEY_POWER:
+ /* Keep track of the power key state */
+ if (up_flag)
+ ahid->flags &= ~FLAG_POWER_KEY_PRESSED;
+ else
+ ahid->flags |= FLAG_POWER_KEY_PRESSED;
+
/* Fn + Command will produce a bogus "power" keycode */
if (ahid->flags & FLAG_FN_KEY_PRESSED) {
keycode = ADB_KEY_CMD;
@@ -681,6 +698,21 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned i
return -1;
}
+static void
+adbhid_kbd_capslock_remember(void)
+{
+ struct adbhid *ahid;
+ int i;
+
+ for (i = 1; i < 16; i++) {
+ ahid = adbhid[i];
+
+ if (ahid && ahid->id == ADB_KEYBOARD)
+ if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE)
+ ahid->flags |= FLAG_CAPSLOCK_IGNORE_NEXT;
+ }
+}
+
static int
adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
{
@@ -697,8 +729,17 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
}
/* Stop pending led requests */
- while(leds_req_pending)
+ while (leds_req_pending)
adb_poll();
+
+ /* After resume, and if the capslock LED is on, the PMU will
+ * send a "capslock down" key event. This confuses the
+ * restore_capslock_events logic. Remember if the capslock
+ * LED was on before suspend so the unwanted key event can
+ * be ignored after resume. */
+ if (restore_capslock_events)
+ adbhid_kbd_capslock_remember();
+
break;
case ADB_MSG_POST_RESET:
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index 67b8e9453b1..ef2dbfe7471 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -40,7 +40,7 @@ static struct mca_bus *mca_root_busses[MAX_MCA_BUSSES];
struct mca_device_info {
short pos_id; /* the 2 byte pos id for this card */
- char name[DEVICE_NAME_SIZE];
+ char name[50];
};
static int mca_bus_match (struct device *dev, struct device_driver *drv)
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index b26927ce889..621a272a2c7 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -225,7 +225,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
|| test_bit(Faulty, &rdev->flags))
continue;
- target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+ target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
page->index = index;
@@ -241,10 +241,10 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
{
mdk_rdev_t *rdev;
- struct list_head *tmp;
mddev_t *mddev = bitmap->mddev;
- rdev_for_each(rdev, tmp, mddev)
+ rcu_read_lock();
+ rdev_for_each_rcu(rdev, mddev)
if (test_bit(In_sync, &rdev->flags)
&& !test_bit(Faulty, &rdev->flags)) {
int size = PAGE_SIZE;
@@ -260,32 +260,37 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
+ (long)(page->index * (PAGE_SIZE/512))
+ size/512 > 0)
/* bitmap runs in to metadata */
- return -EINVAL;
+ goto bad_alignment;
if (rdev->data_offset + mddev->size*2
- > rdev->sb_offset*2 + bitmap->offset)
+ > rdev->sb_start + bitmap->offset)
/* data runs in to bitmap */
- return -EINVAL;
- } else if (rdev->sb_offset*2 < rdev->data_offset) {
+ goto bad_alignment;
+ } else if (rdev->sb_start < rdev->data_offset) {
/* METADATA BITMAP DATA */
- if (rdev->sb_offset*2
+ if (rdev->sb_start
+ bitmap->offset
+ page->index*(PAGE_SIZE/512) + size/512
> rdev->data_offset)
/* bitmap runs in to data */
- return -EINVAL;
+ goto bad_alignment;
} else {
/* DATA METADATA BITMAP - no problems */
}
md_super_write(mddev, rdev,
- (rdev->sb_offset<<1) + bitmap->offset
+ rdev->sb_start + bitmap->offset
+ page->index * (PAGE_SIZE/512),
size,
page);
}
+ rcu_read_unlock();
if (wait)
md_super_wait(mddev);
return 0;
+
+ bad_alignment:
+ rcu_read_unlock();
+ return -EINVAL;
}
static void bitmap_file_kick(struct bitmap *bitmap);
@@ -454,8 +459,11 @@ void bitmap_update_sb(struct bitmap *bitmap)
spin_unlock_irqrestore(&bitmap->lock, flags);
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
sb->events = cpu_to_le64(bitmap->mddev->events);
- if (!bitmap->mddev->degraded)
- sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ if (bitmap->mddev->events < bitmap->events_cleared) {
+ /* rocking back to read-only */
+ bitmap->events_cleared = bitmap->mddev->events;
+ sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
+ }
kunmap_atomic(sb, KM_USER0);
write_page(bitmap, bitmap->sb_page, 1);
}
@@ -1085,9 +1093,19 @@ void bitmap_daemon_work(struct bitmap *bitmap)
} else
spin_unlock_irqrestore(&bitmap->lock, flags);
lastpage = page;
-/*
- printk("bitmap clean at page %lu\n", j);
-*/
+
+ /* We are possibly going to clear some bits, so make
+ * sure that events_cleared is up-to-date.
+ */
+ if (bitmap->need_sync) {
+ bitmap_super_t *sb;
+ bitmap->need_sync = 0;
+ sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+ sb->events_cleared =
+ cpu_to_le64(bitmap->events_cleared);
+ kunmap_atomic(sb, KM_USER0);
+ write_page(bitmap, bitmap->sb_page, 1);
+ }
spin_lock_irqsave(&bitmap->lock, flags);
clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
@@ -1257,6 +1275,12 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
return;
}
+ if (success &&
+ bitmap->events_cleared < bitmap->mddev->events) {
+ bitmap->events_cleared = bitmap->mddev->events;
+ bitmap->need_sync = 1;
+ }
+
if (!success && ! (*bmc & NEEDED_MASK))
*bmc |= NEEDED_MASK;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index ab6a61db63c..13956437bc8 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1216,9 +1216,24 @@ error:
return -EINVAL;
}
+static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+ struct bio_vec *biovec, int max_size)
+{
+ struct crypt_config *cc = ti->private;
+ struct request_queue *q = bdev_get_queue(cc->dev->bdev);
+
+ if (!q->merge_bvec_fn)
+ return max_size;
+
+ bvm->bi_bdev = cc->dev->bdev;
+ bvm->bi_sector = cc->start + bvm->bi_sector - ti->begin;
+
+ return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
static struct target_type crypt_target = {
.name = "crypt",
- .version= {1, 5, 0},
+ .version= {1, 6, 0},
.module = THIS_MODULE,
.ctr = crypt_ctr,
.dtr = crypt_dtr,
@@ -1228,6 +1243,7 @@ static struct target_type crypt_target = {
.preresume = crypt_preresume,
.resume = crypt_resume,
.message = crypt_message,
+ .merge = crypt_merge,
};
static int __init dm_crypt_init(void)
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 17753d80ad2..6449bcdf84c 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -69,13 +69,25 @@ static void linear_dtr(struct dm_target *ti)
kfree(lc);
}
-static int linear_map(struct dm_target *ti, struct bio *bio,
- union map_info *map_context)
+static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
{
- struct linear_c *lc = (struct linear_c *) ti->private;
+ struct linear_c *lc = ti->private;
+
+ return lc->start + (bi_sector - ti->begin);
+}
+
+static void linear_map_bio(struct dm_target *ti, struct bio *bio)
+{
+ struct linear_c *lc = ti->private;
bio->bi_bdev = lc->dev->bdev;
- bio->bi_sector = lc->start + (bio->bi_sector - ti->begin);
+ bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
+}
+
+static int linear_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ linear_map_bio(ti, bio);
return DM_MAPIO_REMAPPED;
}
@@ -114,15 +126,31 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode,
return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
}
+static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+ struct bio_vec *biovec, int max_size)
+{
+ struct linear_c *lc = ti->private;
+ struct request_queue *q = bdev_get_queue(lc->dev->bdev);
+
+ if (!q->merge_bvec_fn)
+ return max_size;
+
+ bvm->bi_bdev = lc->dev->bdev;
+ bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
+
+ return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
static struct target_type linear_target = {
.name = "linear",
- .version= {1, 0, 2},
+ .version= {1, 0, 3},
.module = THIS_MODULE,
.ctr = linear_ctr,
.dtr = linear_dtr,
.map = linear_map,
.status = linear_status,
.ioctl = linear_ioctl,
+ .merge = linear_merge,
};
int __init dm_linear_init(void)
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 67a6f31b7fc..5b48478c79f 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -831,7 +831,7 @@ static struct dm_dirty_log_type _disk_type = {
.status = disk_status,
};
-int __init dm_dirty_log_init(void)
+static int __init dm_dirty_log_init(void)
{
int r;
@@ -848,7 +848,7 @@ int __init dm_dirty_log_init(void)
return r;
}
-void __exit dm_dirty_log_exit(void)
+static void __exit dm_dirty_log_exit(void)
{
dm_dirty_log_type_unregister(&_disk_type);
dm_dirty_log_type_unregister(&_core_type);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 9f7302d4878..fea966d66f9 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -525,8 +525,10 @@ static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
}
r = read_param(_params, shift(as), &ps_argc, &ti->error);
- if (r)
+ if (r) {
+ dm_put_path_selector(pst);
return -EINVAL;
+ }
r = pst->create(&pg->ps, ps_argc, as->argv);
if (r) {
@@ -623,8 +625,10 @@ static struct priority_group *parse_priority_group(struct arg_set *as,
struct pgpath *pgpath;
struct arg_set path_args;
- if (as->argc < nr_params)
+ if (as->argc < nr_params) {
+ ti->error = "not enough path parameters";
goto bad;
+ }
path_args.argc = nr_params;
path_args.argv = as->argv;
@@ -867,7 +871,7 @@ static int reinstate_path(struct pgpath *pgpath)
if (pgpath->path.is_active)
goto out;
- if (!pgpath->pg->ps.type) {
+ if (!pgpath->pg->ps.type->reinstate_path) {
DMWARN("Reinstate path not supported by path selector %s",
pgpath->pg->ps.type->name);
r = -EINVAL;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 1ba8a47d61b..6e5528aecc9 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -40,6 +40,11 @@
*/
#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
+/*
+ * The size of the mempool used to track chunks in use.
+ */
+#define MIN_IOS 256
+
static struct workqueue_struct *ksnapd;
static void flush_queued_bios(struct work_struct *work);
@@ -91,7 +96,63 @@ struct dm_snap_pending_exception {
*/
static struct kmem_cache *exception_cache;
static struct kmem_cache *pending_cache;
-static mempool_t *pending_pool;
+
+struct dm_snap_tracked_chunk {
+ struct hlist_node node;
+ chunk_t chunk;
+};
+
+static struct kmem_cache *tracked_chunk_cache;
+
+static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
+ chunk_t chunk)
+{
+ struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
+ GFP_NOIO);
+ unsigned long flags;
+
+ c->chunk = chunk;
+
+ spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+ hlist_add_head(&c->node,
+ &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
+ spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+
+ return c;
+}
+
+static void stop_tracking_chunk(struct dm_snapshot *s,
+ struct dm_snap_tracked_chunk *c)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+ hlist_del(&c->node);
+ spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+
+ mempool_free(c, s->tracked_chunk_pool);
+}
+
+static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
+{
+ struct dm_snap_tracked_chunk *c;
+ struct hlist_node *hn;
+ int found = 0;
+
+ spin_lock_irq(&s->tracked_chunk_lock);
+
+ hlist_for_each_entry(c, hn,
+ &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) {
+ if (c->chunk == chunk) {
+ found = 1;
+ break;
+ }
+ }
+
+ spin_unlock_irq(&s->tracked_chunk_lock);
+
+ return found;
+}
/*
* One of these per registered origin, held in the snapshot_origins hash
@@ -302,14 +363,19 @@ static void free_exception(struct dm_snap_exception *e)
kmem_cache_free(exception_cache, e);
}
-static struct dm_snap_pending_exception *alloc_pending_exception(void)
+static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s)
{
- return mempool_alloc(pending_pool, GFP_NOIO);
+ struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
+ GFP_NOIO);
+
+ pe->snap = s;
+
+ return pe;
}
static void free_pending_exception(struct dm_snap_pending_exception *pe)
{
- mempool_free(pe, pending_pool);
+ mempool_free(pe, pe->snap->pending_pool);
}
static void insert_completed_exception(struct dm_snapshot *s,
@@ -482,6 +548,7 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg,
static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
struct dm_snapshot *s;
+ int i;
int r = -EINVAL;
char persistent;
char *origin_path;
@@ -564,11 +631,30 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad5;
}
+ s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache);
+ if (!s->pending_pool) {
+ ti->error = "Could not allocate mempool for pending exceptions";
+ goto bad6;
+ }
+
+ s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
+ tracked_chunk_cache);
+ if (!s->tracked_chunk_pool) {
+ ti->error = "Could not allocate tracked_chunk mempool for "
+ "tracking reads";
+ goto bad_tracked_chunk_pool;
+ }
+
+ for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
+
+ spin_lock_init(&s->tracked_chunk_lock);
+
/* Metadata must only be loaded into one table at once */
r = s->store.read_metadata(&s->store);
if (r < 0) {
ti->error = "Failed to read snapshot metadata";
- goto bad6;
+ goto bad_load_and_register;
} else if (r > 0) {
s->valid = 0;
DMWARN("Snapshot is marked invalid.");
@@ -582,7 +668,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (register_snapshot(s)) {
r = -EINVAL;
ti->error = "Cannot register snapshot origin";
- goto bad6;
+ goto bad_load_and_register;
}
ti->private = s;
@@ -590,6 +676,12 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return 0;
+ bad_load_and_register:
+ mempool_destroy(s->tracked_chunk_pool);
+
+ bad_tracked_chunk_pool:
+ mempool_destroy(s->pending_pool);
+
bad6:
dm_kcopyd_client_destroy(s->kcopyd_client);
@@ -624,6 +716,9 @@ static void __free_exceptions(struct dm_snapshot *s)
static void snapshot_dtr(struct dm_target *ti)
{
+#ifdef CONFIG_DM_DEBUG
+ int i;
+#endif
struct dm_snapshot *s = ti->private;
flush_workqueue(ksnapd);
@@ -632,8 +727,17 @@ static void snapshot_dtr(struct dm_target *ti)
/* After this returns there can be no new kcopyd jobs. */
unregister_snapshot(s);
+#ifdef CONFIG_DM_DEBUG
+ for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
+ BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
+#endif
+
+ mempool_destroy(s->tracked_chunk_pool);
+
__free_exceptions(s);
+ mempool_destroy(s->pending_pool);
+
dm_put_device(ti, s->origin);
dm_put_device(ti, s->cow);
@@ -772,6 +876,13 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
}
/*
+ * Check for conflicting reads. This is extremely improbable,
+ * so yield() is sufficient and there is no need for a wait queue.
+ */
+ while (__chunk_is_tracked(s, pe->e.old_chunk))
+ yield();
+
+ /*
* Add a proper exception, and remove the
* in-flight exception from the list.
*/
@@ -873,7 +984,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
* to hold the lock while we do this.
*/
up_write(&s->lock);
- pe = alloc_pending_exception();
+ pe = alloc_pending_exception(s);
down_write(&s->lock);
if (!s->valid) {
@@ -893,7 +1004,6 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
bio_list_init(&pe->snapshot_bios);
pe->primary_pe = NULL;
atomic_set(&pe->ref_count, 0);
- pe->snap = s;
pe->started = 0;
if (s->store.prepare_exception(&s->store, &pe->e)) {
@@ -974,14 +1084,10 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
start_copy(pe);
goto out;
}
- } else
- /*
- * FIXME: this read path scares me because we
- * always use the origin when we have a pending
- * exception. However I can't think of a
- * situation where this is wrong - ejt.
- */
+ } else {
bio->bi_bdev = s->origin->bdev;
+ map_context->ptr = track_chunk(s, chunk);
+ }
out_unlock:
up_write(&s->lock);
@@ -989,6 +1095,18 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
return r;
}
+static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
+ int error, union map_info *map_context)
+{
+ struct dm_snapshot *s = ti->private;
+ struct dm_snap_tracked_chunk *c = map_context->ptr;
+
+ if (c)
+ stop_tracking_chunk(s, c);
+
+ return 0;
+}
+
static void snapshot_resume(struct dm_target *ti)
{
struct dm_snapshot *s = ti->private;
@@ -1266,6 +1384,7 @@ static struct target_type snapshot_target = {
.ctr = snapshot_ctr,
.dtr = snapshot_dtr,
.map = snapshot_map,
+ .end_io = snapshot_end_io,
.resume = snapshot_resume,
.status = snapshot_status,
};
@@ -1306,9 +1425,9 @@ static int __init dm_snapshot_init(void)
goto bad4;
}
- pending_pool = mempool_create_slab_pool(128, pending_cache);
- if (!pending_pool) {
- DMERR("Couldn't create pending pool.");
+ tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
+ if (!tracked_chunk_cache) {
+ DMERR("Couldn't create cache to track chunks in use.");
r = -ENOMEM;
goto bad5;
}
@@ -1317,13 +1436,13 @@ static int __init dm_snapshot_init(void)
if (!ksnapd) {
DMERR("Failed to create ksnapd workqueue.");
r = -ENOMEM;
- goto bad6;
+ goto bad_pending_pool;
}
return 0;
- bad6:
- mempool_destroy(pending_pool);
+ bad_pending_pool:
+ kmem_cache_destroy(tracked_chunk_cache);
bad5:
kmem_cache_destroy(pending_cache);
bad4:
@@ -1352,9 +1471,9 @@ static void __exit dm_snapshot_exit(void)
DMERR("origin unregister failed %d", r);
exit_origin_hash();
- mempool_destroy(pending_pool);
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache);
+ kmem_cache_destroy(tracked_chunk_cache);
}
/* Module hooks */
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 24f9fb73b98..292c15609ae 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -130,6 +130,10 @@ struct exception_store {
void *context;
};
+#define DM_TRACKED_CHUNK_HASH_SIZE 16
+#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \
+ (DM_TRACKED_CHUNK_HASH_SIZE - 1))
+
struct dm_snapshot {
struct rw_semaphore lock;
struct dm_target *ti;
@@ -157,6 +161,8 @@ struct dm_snapshot {
/* The last percentage we notified */
int last_percent;
+ mempool_t *pending_pool;
+
struct exception_table pending;
struct exception_table complete;
@@ -174,6 +180,11 @@ struct dm_snapshot {
/* Queue of snapshot writes for ksnapd to flush */
struct bio_list queued_bios;
struct work_struct queued_bios_work;
+
+ /* Chunks with outstanding reads */
+ mempool_t *tracked_chunk_pool;
+ spinlock_t tracked_chunk_lock;
+ struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
};
/*
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 94116eaf470..798e468103b 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -506,14 +506,13 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev)
rs->max_sectors =
min_not_zero(rs->max_sectors, q->max_sectors);
- /* FIXME: Device-Mapper on top of RAID-0 breaks because DM
- * currently doesn't honor MD's merge_bvec_fn routine.
- * In this case, we'll force DM to use PAGE_SIZE or
- * smaller I/O, just to be safe. A better fix is in the
- * works, but add this for the time being so it will at
- * least operate correctly.
+ /*
+ * Check if merge fn is supported.
+ * If not we'll force DM to use PAGE_SIZE or
+ * smaller I/O, just to be safe.
*/
- if (q->merge_bvec_fn)
+
+ if (q->merge_bvec_fn && !ti->type->merge)
rs->max_sectors =
min_not_zero(rs->max_sectors,
(unsigned int) (PAGE_SIZE >> 9));
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 372369b1cc2..bca448e1187 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -37,8 +37,8 @@ static DEFINE_SPINLOCK(_minor_lock);
struct dm_io {
struct mapped_device *md;
int error;
- struct bio *bio;
atomic_t io_count;
+ struct bio *bio;
unsigned long start_time;
};
@@ -829,6 +829,49 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
* CRUD END
*---------------------------------------------------------------*/
+static int dm_merge_bvec(struct request_queue *q,
+ struct bvec_merge_data *bvm,
+ struct bio_vec *biovec)
+{
+ struct mapped_device *md = q->queuedata;
+ struct dm_table *map = dm_get_table(md);
+ struct dm_target *ti;
+ sector_t max_sectors;
+ int max_size;
+
+ if (unlikely(!map))
+ return 0;
+
+ ti = dm_table_find_target(map, bvm->bi_sector);
+
+ /*
+ * Find maximum amount of I/O that won't need splitting
+ */
+ max_sectors = min(max_io_len(md, bvm->bi_sector, ti),
+ (sector_t) BIO_MAX_SECTORS);
+ max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
+ if (max_size < 0)
+ max_size = 0;
+
+ /*
+ * merge_bvec_fn() returns number of bytes
+ * it can accept at this offset
+ * max is precomputed maximal io size
+ */
+ if (max_size && ti->type->merge)
+ max_size = ti->type->merge(ti, bvm, biovec, max_size);
+
+ /*
+ * Always allow an entire first page
+ */
+ if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
+ max_size = biovec->bv_len;
+
+ dm_table_put(map);
+
+ return max_size;
+}
+
/*
* The request function that just remaps the bio built up by
* dm_merge_bvec.
@@ -1032,6 +1075,7 @@ static struct mapped_device *alloc_dev(int minor)
blk_queue_make_request(md->queue, dm_request);
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
md->queue->unplug_fn = dm_unplug_all;
+ blk_queue_merge_bvec(md->queue, dm_merge_bvec);
md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
if (!md->io_pool)
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8c03b634e62..1e59a0b0a78 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -100,12 +100,6 @@ int dm_lock_for_deletion(struct mapped_device *md);
void dm_kobject_uevent(struct mapped_device *md);
-/*
- * Dirty log
- */
-int dm_dirty_log_init(void);
-void dm_dirty_log_exit(void);
-
int dm_kcopyd_init(void);
void dm_kcopyd_exit(void);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index d107ddceefc..268547dbfbd 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -297,7 +297,7 @@ static int run(mddev_t *mddev)
rdev_for_each(rdev, tmp, mddev)
conf->rdev = rdev;
- mddev->array_size = mddev->size;
+ mddev->array_sectors = mddev->size * 2;
mddev->private = conf;
reconfig(mddev, mddev->layout, -1);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 6a866d7c8ae..b1eebf88c20 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -122,13 +122,13 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
return NULL;
cnt = 0;
- conf->array_size = 0;
+ conf->array_sectors = 0;
rdev_for_each(rdev, tmp, mddev) {
int j = rdev->raid_disk;
dev_info_t *disk = conf->disks + j;
- if (j < 0 || j > raid_disks || disk->rdev) {
+ if (j < 0 || j >= raid_disks || disk->rdev) {
printk("linear: disk numbering problem. Aborting!\n");
goto out;
}
@@ -146,7 +146,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
disk->size = rdev->size;
- conf->array_size += rdev->size;
+ conf->array_sectors += rdev->size * 2;
cnt++;
}
@@ -155,7 +155,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
goto out;
}
- min_spacing = conf->array_size;
+ min_spacing = conf->array_sectors / 2;
sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
/* min_spacing is the minimum spacing that will fit the hash
@@ -164,7 +164,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
* that is larger than min_spacing as use the size of that as
* the actual spacing
*/
- conf->hash_spacing = conf->array_size;
+ conf->hash_spacing = conf->array_sectors / 2;
for (i=0; i < cnt-1 ; i++) {
sector_t sz = 0;
int j;
@@ -194,7 +194,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
unsigned round;
unsigned long base;
- sz = conf->array_size >> conf->preshift;
+ sz = conf->array_sectors >> (conf->preshift + 1);
sz += 1; /* force round-up */
base = conf->hash_spacing >> conf->preshift;
round = sector_div(sz, base);
@@ -221,7 +221,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
curr_offset = 0;
i = 0;
for (curr_offset = 0;
- curr_offset < conf->array_size;
+ curr_offset < conf->array_sectors / 2;
curr_offset += conf->hash_spacing) {
while (i < raid_disks-1 &&
@@ -258,7 +258,7 @@ static int linear_run (mddev_t *mddev)
if (!conf)
return 1;
mddev->private = conf;
- mddev->array_size = conf->array_size;
+ mddev->array_sectors = conf->array_sectors;
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->unplug_fn = linear_unplug;
@@ -292,8 +292,8 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
newconf->prev = mddev_to_conf(mddev);
mddev->private = newconf;
mddev->raid_disks++;
- mddev->array_size = newconf->array_size;
- set_capacity(mddev->gendisk, mddev->array_size << 1);
+ mddev->array_sectors = newconf->array_sectors;
+ set_capacity(mddev->gendisk, mddev->array_sectors);
return 0;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2580ac1b9b0..c2ff77ccec5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -169,7 +169,6 @@ void md_new_event(mddev_t *mddev)
{
atomic_inc(&md_event_count);
wake_up(&md_event_waiters);
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
}
EXPORT_SYMBOL_GPL(md_new_event);
@@ -274,10 +273,12 @@ static mddev_t * mddev_find(dev_t unit)
INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer);
atomic_set(&new->active, 1);
+ atomic_set(&new->openers, 0);
spin_lock_init(&new->write_lock);
init_waitqueue_head(&new->sb_wait);
init_waitqueue_head(&new->recovery_wait);
new->reshape_position = MaxSector;
+ new->resync_min = 0;
new->resync_max = MaxSector;
new->level = LEVEL_NONE;
@@ -347,21 +348,20 @@ static struct mdk_personality *find_pers(int level, char *clevel)
return NULL;
}
+/* return the offset of the super block in 512byte sectors */
static inline sector_t calc_dev_sboffset(struct block_device *bdev)
{
- sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
- return MD_NEW_SIZE_BLOCKS(size);
+ sector_t num_sectors = bdev->bd_inode->i_size / 512;
+ return MD_NEW_SIZE_SECTORS(num_sectors);
}
-static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size)
+static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
{
- sector_t size;
-
- size = rdev->sb_offset;
+ sector_t num_sectors = rdev->sb_start;
if (chunk_size)
- size &= ~((sector_t)chunk_size/1024 - 1);
- return size;
+ num_sectors &= ~((sector_t)chunk_size/512 - 1);
+ return num_sectors;
}
static int alloc_disk_sb(mdk_rdev_t * rdev)
@@ -372,7 +372,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
rdev->sb_page = alloc_page(GFP_KERNEL);
if (!rdev->sb_page) {
printk(KERN_ALERT "md: out of memory.\n");
- return -EINVAL;
+ return -ENOMEM;
}
return 0;
@@ -384,7 +384,7 @@ static void free_disk_sb(mdk_rdev_t * rdev)
put_page(rdev->sb_page);
rdev->sb_loaded = 0;
rdev->sb_page = NULL;
- rdev->sb_offset = 0;
+ rdev->sb_start = 0;
rdev->size = 0;
}
}
@@ -530,7 +530,7 @@ static int read_disk_sb(mdk_rdev_t * rdev, int size)
return 0;
- if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
+ if (!sync_page_io(rdev->bdev, rdev->sb_start, size, rdev->sb_page, READ))
goto fail;
rdev->sb_loaded = 1;
return 0;
@@ -543,17 +543,12 @@ fail:
static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
{
- if ( (sb1->set_uuid0 == sb2->set_uuid0) &&
- (sb1->set_uuid1 == sb2->set_uuid1) &&
- (sb1->set_uuid2 == sb2->set_uuid2) &&
- (sb1->set_uuid3 == sb2->set_uuid3))
-
- return 1;
-
- return 0;
+ return sb1->set_uuid0 == sb2->set_uuid0 &&
+ sb1->set_uuid1 == sb2->set_uuid1 &&
+ sb1->set_uuid2 == sb2->set_uuid2 &&
+ sb1->set_uuid3 == sb2->set_uuid3;
}
-
static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
{
int ret;
@@ -564,7 +559,7 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
if (!tmp1 || !tmp2) {
ret = 0;
- printk(KERN_INFO "md.c: sb1 is not equal to sb2!\n");
+ printk(KERN_INFO "md.c sb_equal(): failed to allocate memory!\n");
goto abort;
}
@@ -577,11 +572,7 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
tmp1->nr_disks = 0;
tmp2->nr_disks = 0;
- if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4))
- ret = 0;
- else
- ret = 1;
-
+ ret = (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4) == 0);
abort:
kfree(tmp1);
kfree(tmp2);
@@ -658,11 +649,14 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
*/
struct super_type {
- char *name;
- struct module *owner;
- int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version);
- int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
- void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+ char *name;
+ struct module *owner;
+ int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+ int minor_version);
+ int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+ void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+ unsigned long long (*rdev_size_change)(mdk_rdev_t *rdev,
+ sector_t num_sectors);
};
/*
@@ -673,16 +667,14 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
mdp_super_t *sb;
int ret;
- sector_t sb_offset;
/*
- * Calculate the position of the superblock,
+ * Calculate the position of the superblock (512byte sectors),
* it's at the end of the disk.
*
* It also happens to be a multiple of 4Kb.
*/
- sb_offset = calc_dev_sboffset(rdev->bdev);
- rdev->sb_offset = sb_offset;
+ rdev->sb_start = calc_dev_sboffset(rdev->bdev);
ret = read_disk_sb(rdev, MD_SB_BYTES);
if (ret) return ret;
@@ -759,7 +751,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
else
ret = 0;
}
- rdev->size = calc_dev_size(rdev, sb->chunk_size);
+ rdev->size = calc_num_sectors(rdev, sb->chunk_size) / 2;
if (rdev->size < sb->size && sb->level > 1)
/* "this cannot possibly happen" ... */
@@ -1004,6 +996,26 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
}
/*
+ * rdev_size_change for 0.90.0
+ */
+static unsigned long long
+super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+{
+ if (num_sectors && num_sectors < rdev->mddev->size * 2)
+ return 0; /* component must fit device */
+ if (rdev->mddev->bitmap_offset)
+ return 0; /* can't move bitmap */
+ rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+ if (!num_sectors || num_sectors > rdev->sb_start)
+ num_sectors = rdev->sb_start;
+ md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+ rdev->sb_page);
+ md_super_wait(rdev->mddev);
+ return num_sectors / 2; /* kB for sysfs */
+}
+
+
+/*
* version 1 superblock
*/
@@ -1034,12 +1046,12 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
{
struct mdp_superblock_1 *sb;
int ret;
- sector_t sb_offset;
+ sector_t sb_start;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
int bmask;
/*
- * Calculate the position of the superblock.
+ * Calculate the position of the superblock in 512byte sectors.
* It is always aligned to a 4K boundary and
* depeding on minor_version, it can be:
* 0: At least 8K, but less than 12K, from end of device
@@ -1048,22 +1060,20 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
*/
switch(minor_version) {
case 0:
- sb_offset = rdev->bdev->bd_inode->i_size >> 9;
- sb_offset -= 8*2;
- sb_offset &= ~(sector_t)(4*2-1);
- /* convert from sectors to K */
- sb_offset /= 2;
+ sb_start = rdev->bdev->bd_inode->i_size >> 9;
+ sb_start -= 8*2;
+ sb_start &= ~(sector_t)(4*2-1);
break;
case 1:
- sb_offset = 0;
+ sb_start = 0;
break;
case 2:
- sb_offset = 4;
+ sb_start = 8;
break;
default:
return -EINVAL;
}
- rdev->sb_offset = sb_offset;
+ rdev->sb_start = sb_start;
/* superblock is rarely larger than 1K, but it can be larger,
* and it is safe to read 4k, so we do that
@@ -1077,7 +1087,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
if (sb->magic != cpu_to_le32(MD_SB_MAGIC) ||
sb->major_version != cpu_to_le32(1) ||
le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
- le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
+ le64_to_cpu(sb->super_offset) != rdev->sb_start ||
(le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
return -EINVAL;
@@ -1113,7 +1123,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->sb_size = (rdev->sb_size | bmask) + 1;
if (minor_version
- && rdev->data_offset < sb_offset + (rdev->sb_size/512))
+ && rdev->data_offset < sb_start + (rdev->sb_size/512))
return -EINVAL;
if (sb->level == cpu_to_le32(LEVEL_MULTIPATH))
@@ -1149,7 +1159,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
if (minor_version)
rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2;
else
- rdev->size = rdev->sb_offset;
+ rdev->size = rdev->sb_start / 2;
if (rdev->size < le64_to_cpu(sb->data_size)/2)
return -EINVAL;
rdev->size = le64_to_cpu(sb->data_size)/2;
@@ -1328,35 +1338,74 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->sb_csum = calc_sb_1_csum(sb);
}
+static unsigned long long
+super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+{
+ struct mdp_superblock_1 *sb;
+ sector_t max_sectors;
+ if (num_sectors && num_sectors < rdev->mddev->size * 2)
+ return 0; /* component must fit device */
+ if (rdev->sb_start < rdev->data_offset) {
+ /* minor versions 1 and 2; superblock before data */
+ max_sectors = rdev->bdev->bd_inode->i_size >> 9;
+ max_sectors -= rdev->data_offset;
+ if (!num_sectors || num_sectors > max_sectors)
+ num_sectors = max_sectors;
+ } else if (rdev->mddev->bitmap_offset) {
+ /* minor version 0 with bitmap we can't move */
+ return 0;
+ } else {
+ /* minor version 0; superblock after data */
+ sector_t sb_start;
+ sb_start = (rdev->bdev->bd_inode->i_size >> 9) - 8*2;
+ sb_start &= ~(sector_t)(4*2 - 1);
+ max_sectors = rdev->size * 2 + sb_start - rdev->sb_start;
+ if (!num_sectors || num_sectors > max_sectors)
+ num_sectors = max_sectors;
+ rdev->sb_start = sb_start;
+ }
+ sb = (struct mdp_superblock_1 *) page_address(rdev->sb_page);
+ sb->data_size = cpu_to_le64(num_sectors);
+ sb->super_offset = rdev->sb_start;
+ sb->sb_csum = calc_sb_1_csum(sb);
+ md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+ rdev->sb_page);
+ md_super_wait(rdev->mddev);
+ return num_sectors / 2; /* kB for sysfs */
+}
static struct super_type super_types[] = {
[0] = {
.name = "0.90.0",
.owner = THIS_MODULE,
- .load_super = super_90_load,
- .validate_super = super_90_validate,
- .sync_super = super_90_sync,
+ .load_super = super_90_load,
+ .validate_super = super_90_validate,
+ .sync_super = super_90_sync,
+ .rdev_size_change = super_90_rdev_size_change,
},
[1] = {
.name = "md-1",
.owner = THIS_MODULE,
- .load_super = super_1_load,
- .validate_super = super_1_validate,
- .sync_super = super_1_sync,
+ .load_super = super_1_load,
+ .validate_super = super_1_validate,
+ .sync_super = super_1_sync,
+ .rdev_size_change = super_1_rdev_size_change,
},
};
static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
{
- struct list_head *tmp, *tmp2;
mdk_rdev_t *rdev, *rdev2;
- rdev_for_each(rdev, tmp, mddev1)
- rdev_for_each(rdev2, tmp2, mddev2)
+ rcu_read_lock();
+ rdev_for_each_rcu(rdev, mddev1)
+ rdev_for_each_rcu(rdev2, mddev2)
if (rdev->bdev->bd_contains ==
- rdev2->bdev->bd_contains)
+ rdev2->bdev->bd_contains) {
+ rcu_read_unlock();
return 1;
-
+ }
+ rcu_read_unlock();
return 0;
}
@@ -1423,7 +1472,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
kobject_del(&rdev->kobj);
goto fail;
}
- list_add(&rdev->same_set, &mddev->disks);
+ list_add_rcu(&rdev->same_set, &mddev->disks);
bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
return 0;
@@ -1448,14 +1497,16 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
return;
}
bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
- list_del_init(&rdev->same_set);
+ list_del_rcu(&rdev->same_set);
printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
rdev->mddev = NULL;
sysfs_remove_link(&rdev->kobj, "block");
/* We need to delay this, otherwise we can deadlock when
- * writing to 'remove' to "dev/state"
+ * writing to 'remove' to "dev/state". We also need
+ * to delay it due to rcu usage.
*/
+ synchronize_rcu();
INIT_WORK(&rdev->del_work, md_delayed_delete);
kobject_get(&rdev->kobj);
schedule_work(&rdev->del_work);
@@ -1511,7 +1562,6 @@ static void export_rdev(mdk_rdev_t * rdev)
if (rdev->mddev)
MD_BUG();
free_disk_sb(rdev);
- list_del_init(&rdev->same_set);
#ifndef MODULE
if (test_bit(AutoDetected, &rdev->flags))
md_autodetect_dev(rdev->bdev->bd_dev);
@@ -1758,11 +1808,11 @@ repeat:
dprintk("%s ", bdevname(rdev->bdev,b));
if (!test_bit(Faulty, &rdev->flags)) {
md_super_write(mddev,rdev,
- rdev->sb_offset<<1, rdev->sb_size,
+ rdev->sb_start, rdev->sb_size,
rdev->sb_page);
dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
bdevname(rdev->bdev,b),
- (unsigned long long)rdev->sb_offset);
+ (unsigned long long)rdev->sb_start);
rdev->sb_events = mddev->events;
} else
@@ -1787,7 +1837,7 @@ repeat:
}
-/* words written to sysfs files may, or my not, be \n terminated.
+/* words written to sysfs files may, or may not, be \n terminated.
* We want to accept with case. For this we use cmd_match.
*/
static int cmd_match(const char *cmd, const char *str)
@@ -1886,6 +1936,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
err = 0;
}
+ if (!err)
+ sysfs_notify(&rdev->kobj, NULL, "state");
return err ? err : len;
}
static struct rdev_sysfs_entry rdev_state =
@@ -1931,7 +1983,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
slot = -1;
else if (e==buf || (*e && *e!= '\n'))
return -EINVAL;
- if (rdev->mddev->pers) {
+ if (rdev->mddev->pers && slot == -1) {
/* Setting 'slot' on an active array requires also
* updating the 'rd%d' link, and communicating
* with the personality with ->hot_*_disk.
@@ -1939,8 +1991,6 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
* failed/spare devices. This normally happens automatically,
* but not when the metadata is externally managed.
*/
- if (slot != -1)
- return -EBUSY;
if (rdev->raid_disk == -1)
return -EEXIST;
/* personality does all needed checks */
@@ -1954,6 +2004,43 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
sysfs_remove_link(&rdev->mddev->kobj, nm);
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
md_wakeup_thread(rdev->mddev->thread);
+ } else if (rdev->mddev->pers) {
+ mdk_rdev_t *rdev2;
+ struct list_head *tmp;
+ /* Activating a spare .. or possibly reactivating
+ * if we every get bitmaps working here.
+ */
+
+ if (rdev->raid_disk != -1)
+ return -EBUSY;
+
+ if (rdev->mddev->pers->hot_add_disk == NULL)
+ return -EINVAL;
+
+ rdev_for_each(rdev2, tmp, rdev->mddev)
+ if (rdev2->raid_disk == slot)
+ return -EEXIST;
+
+ rdev->raid_disk = slot;
+ if (test_bit(In_sync, &rdev->flags))
+ rdev->saved_raid_disk = slot;
+ else
+ rdev->saved_raid_disk = -1;
+ err = rdev->mddev->pers->
+ hot_add_disk(rdev->mddev, rdev);
+ if (err) {
+ rdev->raid_disk = -1;
+ return err;
+ } else
+ sysfs_notify(&rdev->kobj, NULL, "state");
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
+ printk(KERN_WARNING
+ "md: cannot register "
+ "%s for %s\n",
+ nm, mdname(rdev->mddev));
+
+ /* don't wakeup anyone, leave that to userspace. */
} else {
if (slot >= rdev->mddev->raid_disks)
return -ENOSPC;
@@ -1962,6 +2049,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
clear_bit(Faulty, &rdev->flags);
clear_bit(WriteMostly, &rdev->flags);
set_bit(In_sync, &rdev->flags);
+ sysfs_notify(&rdev->kobj, NULL, "state");
}
return len;
}
@@ -1983,7 +2071,7 @@ offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
unsigned long long offset = simple_strtoull(buf, &e, 10);
if (e==buf || (*e && *e != '\n'))
return -EINVAL;
- if (rdev->mddev->pers)
+ if (rdev->mddev->pers && rdev->raid_disk >= 0)
return -EBUSY;
if (rdev->size && rdev->mddev->external)
/* Must set offset before size, so overlap checks
@@ -2015,17 +2103,30 @@ static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
static ssize_t
rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
{
- char *e;
- unsigned long long size = simple_strtoull(buf, &e, 10);
+ unsigned long long size;
unsigned long long oldsize = rdev->size;
mddev_t *my_mddev = rdev->mddev;
- if (e==buf || (*e && *e != '\n'))
+ if (strict_strtoull(buf, 10, &size) < 0)
return -EINVAL;
- if (my_mddev->pers)
- return -EBUSY;
+ if (size < my_mddev->size)
+ return -EINVAL;
+ if (my_mddev->pers && rdev->raid_disk >= 0) {
+ if (my_mddev->persistent) {
+ size = super_types[my_mddev->major_version].
+ rdev_size_change(rdev, size * 2);
+ if (!size)
+ return -EBUSY;
+ } else if (!size) {
+ size = (rdev->bdev->bd_inode->i_size >> 10);
+ size -= rdev->data_offset/2;
+ }
+ if (size < my_mddev->size)
+ return -EINVAL; /* component must fit device */
+ }
+
rdev->size = size;
- if (size > oldsize && rdev->mddev->external) {
+ if (size > oldsize && my_mddev->external) {
/* need to check that all other rdevs with the same ->bdev
* do not overlap. We need to unlock the mddev to avoid
* a deadlock. We have already changed rdev->size, and if
@@ -2044,8 +2145,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
if (test_bit(AllReserved, &rdev2->flags) ||
(rdev->bdev == rdev2->bdev &&
rdev != rdev2 &&
- overlaps(rdev->data_offset, rdev->size,
- rdev2->data_offset, rdev2->size))) {
+ overlaps(rdev->data_offset, rdev->size * 2,
+ rdev2->data_offset,
+ rdev2->size * 2))) {
overlap = 1;
break;
}
@@ -2067,8 +2169,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
return -EBUSY;
}
}
- if (size < my_mddev->size || my_mddev->size == 0)
- my_mddev->size = size;
return len;
}
@@ -2512,7 +2612,7 @@ __ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store);
* When written, doesn't tear down array, but just stops it
* suspended (not supported yet)
* All IO requests will block. The array can be reconfigured.
- * Writing this, if accepted, will block until array is quiessent
+ * Writing this, if accepted, will block until array is quiescent
* readonly
* no resync can happen. no superblocks get written.
* write requests fail
@@ -2585,7 +2685,7 @@ array_state_show(mddev_t *mddev, char *page)
return sprintf(page, "%s\n", array_states[st]);
}
-static int do_md_stop(mddev_t * mddev, int ro);
+static int do_md_stop(mddev_t * mddev, int ro, int is_open);
static int do_md_run(mddev_t * mddev);
static int restart_array(mddev_t *mddev);
@@ -2599,16 +2699,16 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break;
case clear:
/* stopping an active array */
- if (atomic_read(&mddev->active) > 1)
+ if (atomic_read(&mddev->openers) > 0)
return -EBUSY;
- err = do_md_stop(mddev, 0);
+ err = do_md_stop(mddev, 0, 0);
break;
case inactive:
/* stopping an active array */
if (mddev->pers) {
- if (atomic_read(&mddev->active) > 1)
+ if (atomic_read(&mddev->openers) > 0)
return -EBUSY;
- err = do_md_stop(mddev, 2);
+ err = do_md_stop(mddev, 2, 0);
} else
err = 0; /* already inactive */
break;
@@ -2616,7 +2716,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break; /* not supported yet */
case readonly:
if (mddev->pers)
- err = do_md_stop(mddev, 1);
+ err = do_md_stop(mddev, 1, 0);
else {
mddev->ro = 1;
set_disk_ro(mddev->gendisk, 1);
@@ -2626,7 +2726,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
case read_auto:
if (mddev->pers) {
if (mddev->ro != 1)
- err = do_md_stop(mddev, 1);
+ err = do_md_stop(mddev, 1, 0);
else
err = restart_array(mddev);
if (err == 0) {
@@ -2681,8 +2781,10 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
}
if (err)
return err;
- else
+ else {
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
return len;
+ }
}
static struct md_sysfs_entry md_array_state =
__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
@@ -2785,7 +2887,7 @@ size_show(mddev_t *mddev, char *page)
return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
}
-static int update_size(mddev_t *mddev, unsigned long size);
+static int update_size(mddev_t *mddev, sector_t num_sectors);
static ssize_t
size_store(mddev_t *mddev, const char *buf, size_t len)
@@ -2802,7 +2904,7 @@ size_store(mddev_t *mddev, const char *buf, size_t len)
return -EINVAL;
if (mddev->pers) {
- err = update_size(mddev, size);
+ err = update_size(mddev, size * 2);
md_update_sb(mddev, 1);
} else {
if (mddev->size == 0 ||
@@ -2899,7 +3001,7 @@ action_show(mddev_t *mddev, char *page)
type = "check";
else
type = "repair";
- } else
+ } else if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery))
type = "recover";
}
return sprintf(page, "%s\n", type);
@@ -2921,15 +3023,19 @@ action_store(mddev_t *mddev, const char *page, size_t len)
} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
return -EBUSY;
- else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
+ else if (cmd_match(page, "resync"))
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ else if (cmd_match(page, "recover")) {
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- else if (cmd_match(page, "reshape")) {
+ } else if (cmd_match(page, "reshape")) {
int err;
if (mddev->pers->start_reshape == NULL)
return -EINVAL;
err = mddev->pers->start_reshape(mddev);
if (err)
return err;
+ sysfs_notify(&mddev->kobj, NULL, "degraded");
} else {
if (cmd_match(page, "check"))
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
@@ -2940,6 +3046,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
}
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
return len;
}
@@ -3049,11 +3156,11 @@ static ssize_t
sync_speed_show(mddev_t *mddev, char *page)
{
unsigned long resync, dt, db;
- resync = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active));
- dt = ((jiffies - mddev->resync_mark) / HZ);
+ resync = mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active);
+ dt = (jiffies - mddev->resync_mark) / HZ;
if (!dt) dt++;
- db = resync - (mddev->resync_mark_cnt);
- return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
+ db = resync - mddev->resync_mark_cnt;
+ return sprintf(page, "%lu\n", db/dt/2); /* K/sec */
}
static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
@@ -3075,6 +3182,36 @@ sync_completed_show(mddev_t *mddev, char *page)
static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
static ssize_t
+min_sync_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n",
+ (unsigned long long)mddev->resync_min);
+}
+static ssize_t
+min_sync_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ unsigned long long min;
+ if (strict_strtoull(buf, 10, &min))
+ return -EINVAL;
+ if (min > mddev->resync_max)
+ return -EINVAL;
+ if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+ return -EBUSY;
+
+ /* Must be a multiple of chunk_size */
+ if (mddev->chunk_size) {
+ if (min & (sector_t)((mddev->chunk_size>>9)-1))
+ return -EINVAL;
+ }
+ mddev->resync_min = min;
+
+ return len;
+}
+
+static struct md_sysfs_entry md_min_sync =
+__ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
+
+static ssize_t
max_sync_show(mddev_t *mddev, char *page)
{
if (mddev->resync_max == MaxSector)
@@ -3089,9 +3226,10 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
if (strncmp(buf, "max", 3) == 0)
mddev->resync_max = MaxSector;
else {
- char *ep;
- unsigned long long max = simple_strtoull(buf, &ep, 10);
- if (ep == buf || (*ep != 0 && *ep != '\n'))
+ unsigned long long max;
+ if (strict_strtoull(buf, 10, &max))
+ return -EINVAL;
+ if (max < mddev->resync_min)
return -EINVAL;
if (max < mddev->resync_max &&
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3222,6 +3360,7 @@ static struct attribute *md_redundancy_attrs[] = {
&md_sync_speed.attr,
&md_sync_force_parallel.attr,
&md_sync_completed.attr,
+ &md_min_sync.attr,
&md_max_sync.attr,
&md_suspend_lo.attr,
&md_suspend_hi.attr,
@@ -3326,9 +3465,9 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
disk->queue = mddev->queue;
add_disk(disk);
mddev->gendisk = disk;
- mutex_unlock(&disks_mutex);
error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj,
"%s", "md");
+ mutex_unlock(&disks_mutex);
if (error)
printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
disk->disk_name);
@@ -3341,7 +3480,11 @@ static void md_safemode_timeout(unsigned long data)
{
mddev_t *mddev = (mddev_t *) data;
- mddev->safemode = 1;
+ if (!atomic_read(&mddev->writes_pending)) {
+ mddev->safemode = 1;
+ if (mddev->external)
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
+ }
md_wakeup_thread(mddev->thread);
}
@@ -3432,22 +3575,23 @@ static int do_md_run(mddev_t * mddev)
* We don't want the data to overlap the metadata,
* Internal Bitmap issues has handled elsewhere.
*/
- if (rdev->data_offset < rdev->sb_offset) {
+ if (rdev->data_offset < rdev->sb_start) {
if (mddev->size &&
rdev->data_offset + mddev->size*2
- > rdev->sb_offset*2) {
+ > rdev->sb_start) {
printk("md: %s: data overlaps metadata\n",
mdname(mddev));
return -EINVAL;
}
} else {
- if (rdev->sb_offset*2 + rdev->sb_size/512
+ if (rdev->sb_start + rdev->sb_size/512
> rdev->data_offset) {
printk("md: %s: metadata overlaps data\n",
mdname(mddev));
return -EINVAL;
}
}
+ sysfs_notify(&rdev->kobj, NULL, "state");
}
md_probe(mddev->unit, NULL, NULL);
@@ -3519,7 +3663,9 @@ static int do_md_run(mddev_t * mddev)
mddev->ro = 2; /* read-only, but switch on first write */
err = mddev->pers->run(mddev);
- if (!err && mddev->pers->sync_request) {
+ if (err)
+ printk(KERN_ERR "md: pers->run() failed ...\n");
+ else if (mddev->pers->sync_request) {
err = bitmap_create(mddev);
if (err) {
printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
@@ -3528,7 +3674,6 @@ static int do_md_run(mddev_t * mddev)
}
}
if (err) {
- printk(KERN_ERR "md: pers->run() failed ...\n");
module_put(mddev->pers->owner);
mddev->pers = NULL;
bitmap_destroy(mddev);
@@ -3563,7 +3708,7 @@ static int do_md_run(mddev_t * mddev)
if (mddev->flags)
md_update_sb(mddev, 0);
- set_capacity(disk, mddev->array_size<<1);
+ set_capacity(disk, mddev->array_sectors);
/* If we call blk_queue_make_request here, it will
* re-initialise max_sectors etc which may have been
@@ -3608,6 +3753,9 @@ static int do_md_run(mddev_t * mddev)
mddev->changed = 1;
md_new_event(mddev);
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ sysfs_notify(&mddev->kobj, NULL, "degraded");
kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
return 0;
}
@@ -3615,38 +3763,25 @@ static int do_md_run(mddev_t * mddev)
static int restart_array(mddev_t *mddev)
{
struct gendisk *disk = mddev->gendisk;
- int err;
- /*
- * Complain if it has no devices
- */
- err = -ENXIO;
+ /* Complain if it has no devices */
if (list_empty(&mddev->disks))
- goto out;
-
- if (mddev->pers) {
- err = -EBUSY;
- if (!mddev->ro)
- goto out;
-
- mddev->safemode = 0;
- mddev->ro = 0;
- set_disk_ro(disk, 0);
-
- printk(KERN_INFO "md: %s switched to read-write mode.\n",
- mdname(mddev));
- /*
- * Kick recovery or resync if necessary
- */
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- md_wakeup_thread(mddev->thread);
- md_wakeup_thread(mddev->sync_thread);
- err = 0;
- } else
- err = -EINVAL;
-
-out:
- return err;
+ return -ENXIO;
+ if (!mddev->pers)
+ return -EINVAL;
+ if (!mddev->ro)
+ return -EBUSY;
+ mddev->safemode = 0;
+ mddev->ro = 0;
+ set_disk_ro(disk, 0);
+ printk(KERN_INFO "md: %s switched to read-write mode.\n",
+ mdname(mddev));
+ /* Kick recovery or resync if necessary */
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_wakeup_thread(mddev->thread);
+ md_wakeup_thread(mddev->sync_thread);
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
+ return 0;
}
/* similar to deny_write_access, but accounts for our holding a reference
@@ -3680,16 +3815,17 @@ static void restore_bitmap_write_access(struct file *file)
* 1 - switch to readonly
* 2 - stop but do not disassemble array
*/
-static int do_md_stop(mddev_t * mddev, int mode)
+static int do_md_stop(mddev_t * mddev, int mode, int is_open)
{
int err = 0;
struct gendisk *disk = mddev->gendisk;
+ if (atomic_read(&mddev->openers) > is_open) {
+ printk("md: %s still in use.\n",mdname(mddev));
+ return -EBUSY;
+ }
+
if (mddev->pers) {
- if (atomic_read(&mddev->active)>2) {
- printk("md: %s still in use.\n",mdname(mddev));
- return -EBUSY;
- }
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -3773,10 +3909,11 @@ static int do_md_stop(mddev_t * mddev, int mode)
export_array(mddev);
- mddev->array_size = 0;
+ mddev->array_sectors = 0;
mddev->size = 0;
mddev->raid_disks = 0;
mddev->recovery_cp = 0;
+ mddev->resync_min = 0;
mddev->resync_max = MaxSector;
mddev->reshape_position = MaxSector;
mddev->external = 0;
@@ -3811,6 +3948,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
mdname(mddev));
err = 0;
md_new_event(mddev);
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
out:
return err;
}
@@ -3836,7 +3974,7 @@ static void autorun_array(mddev_t *mddev)
err = do_md_run (mddev);
if (err) {
printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
- do_md_stop (mddev, 0);
+ do_md_stop (mddev, 0, 0);
}
}
@@ -3927,8 +4065,10 @@ static void autorun_devices(int part)
/* on success, candidates will be empty, on error
* it won't...
*/
- rdev_for_each_list(rdev, tmp, candidates)
+ rdev_for_each_list(rdev, tmp, candidates) {
+ list_del_init(&rdev->same_set);
export_rdev(rdev);
+ }
mddev_put(mddev);
}
printk(KERN_INFO "md: ... autorun DONE.\n");
@@ -4009,9 +4149,11 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg)
char *ptr, *buf = NULL;
int err = -ENOMEM;
- md_allow_write(mddev);
+ if (md_allow_write(mddev))
+ file = kmalloc(sizeof(*file), GFP_NOIO);
+ else
+ file = kmalloc(sizeof(*file), GFP_KERNEL);
- file = kmalloc(sizeof(*file), GFP_KERNEL);
if (!file)
goto out;
@@ -4044,15 +4186,12 @@ out:
static int get_disk_info(mddev_t * mddev, void __user * arg)
{
mdu_disk_info_t info;
- unsigned int nr;
mdk_rdev_t *rdev;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
- nr = info.number;
-
- rdev = find_rdev_nr(mddev, nr);
+ rdev = find_rdev_nr(mddev, info.number);
if (rdev) {
info.major = MAJOR(rdev->bdev->bd_dev);
info.minor = MINOR(rdev->bdev->bd_dev);
@@ -4172,8 +4311,12 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
}
if (err)
export_rdev(rdev);
+ else
+ sysfs_notify(&rdev->kobj, NULL, "state");
md_update_sb(mddev, 1);
+ if (mddev->degraded)
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
return err;
@@ -4212,10 +4355,10 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (!mddev->persistent) {
printk(KERN_INFO "md: nonpersistent superblock ...\n");
- rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+ rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
} else
- rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
- rdev->size = calc_dev_size(rdev, mddev->chunk_size);
+ rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+ rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
err = bind_rdev_to_array(rdev, mddev);
if (err) {
@@ -4232,9 +4375,6 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
char b[BDEVNAME_SIZE];
mdk_rdev_t *rdev;
- if (!mddev->pers)
- return -ENODEV;
-
rdev = find_rdev(mddev, dev);
if (!rdev)
return -ENXIO;
@@ -4257,7 +4397,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
{
char b[BDEVNAME_SIZE];
int err;
- unsigned int size;
mdk_rdev_t *rdev;
if (!mddev->pers)
@@ -4285,13 +4424,11 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
}
if (mddev->persistent)
- rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+ rdev->sb_start = calc_dev_sboffset(rdev->bdev);
else
- rdev->sb_offset =
- rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+ rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
- size = calc_dev_size(rdev, mddev->chunk_size);
- rdev->size = size;
+ rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
if (test_bit(Faulty, &rdev->flags)) {
printk(KERN_WARNING
@@ -4476,24 +4613,24 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
return 0;
}
-static int update_size(mddev_t *mddev, unsigned long size)
+static int update_size(mddev_t *mddev, sector_t num_sectors)
{
mdk_rdev_t * rdev;
int rv;
struct list_head *tmp;
- int fit = (size == 0);
+ int fit = (num_sectors == 0);
if (mddev->pers->resize == NULL)
return -EINVAL;
- /* The "size" is the amount of each device that is used.
- * This can only make sense for arrays with redundancy.
- * linear and raid0 always use whatever space is available
- * We can only consider changing the size if no resync
- * or reconstruction is happening, and if the new size
- * is acceptable. It must fit before the sb_offset or,
- * if that is <data_offset, it must fit before the
- * size of each device.
- * If size is zero, we find the largest size that fits.
+ /* The "num_sectors" is the number of sectors of each device that
+ * is used. This can only make sense for arrays with redundancy.
+ * linear and raid0 always use whatever space is available. We can only
+ * consider changing this number if no resync or reconstruction is
+ * happening, and if the new size is acceptable. It must fit before the
+ * sb_start or, if that is <data_offset, it must fit before the size
+ * of each device. If num_sectors is zero, we find the largest size
+ * that fits.
+
*/
if (mddev->sync_thread)
return -EBUSY;
@@ -4501,19 +4638,20 @@ static int update_size(mddev_t *mddev, unsigned long size)
sector_t avail;
avail = rdev->size * 2;
- if (fit && (size == 0 || size > avail/2))
- size = avail/2;
- if (avail < ((sector_t)size << 1))
+ if (fit && (num_sectors == 0 || num_sectors > avail))
+ num_sectors = avail;
+ if (avail < num_sectors)
return -ENOSPC;
}
- rv = mddev->pers->resize(mddev, (sector_t)size *2);
+ rv = mddev->pers->resize(mddev, num_sectors);
if (!rv) {
struct block_device *bdev;
bdev = bdget_disk(mddev->gendisk, 0);
if (bdev) {
mutex_lock(&bdev->bd_inode->i_mutex);
- i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10);
+ i_size_write(bdev->bd_inode,
+ (loff_t)mddev->array_sectors << 9);
mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
@@ -4588,7 +4726,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
return mddev->pers->reconfig(mddev, info->layout, -1);
}
if (info->size >= 0 && mddev->size != info->size)
- rv = update_size(mddev, info->size);
+ rv = update_size(mddev, (sector_t)info->size * 2);
if (mddev->raid_disks != info->raid_disks)
rv = update_raid_disks(mddev, info->raid_disks);
@@ -4641,6 +4779,12 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
return 0;
}
+/*
+ * We have a problem here : there is no easy way to give a CHS
+ * virtual geometry. We currently pretend that we have a 2 heads
+ * 4 sectors (with a BIG number of cylinders...). This drives
+ * dosfs just mad... ;-)
+ */
static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
mddev_t *mddev = bdev->bd_disk->private_data;
@@ -4785,19 +4929,13 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock;
case STOP_ARRAY:
- err = do_md_stop (mddev, 0);
+ err = do_md_stop (mddev, 0, 1);
goto done_unlock;
case STOP_ARRAY_RO:
- err = do_md_stop (mddev, 1);
+ err = do_md_stop (mddev, 1, 1);
goto done_unlock;
- /*
- * We have a problem here : there is no easy way to give a CHS
- * virtual geometry. We currently pretend that we have a 2 heads
- * 4 sectors (with a BIG number of cylinders...). This drives
- * dosfs just mad... ;-)
- */
}
/*
@@ -4807,13 +4945,12 @@ static int md_ioctl(struct inode *inode, struct file *file,
* here and hit the 'default' below, so only disallow
* 'md' ioctls, and switch to rw mode if started auto-readonly.
*/
- if (_IOC_TYPE(cmd) == MD_MAJOR &&
- mddev->ro && mddev->pers) {
+ if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) {
if (mddev->ro == 2) {
mddev->ro = 0;
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- md_wakeup_thread(mddev->thread);
-
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_wakeup_thread(mddev->thread);
} else {
err = -EROFS;
goto abort_unlock;
@@ -4883,6 +5020,7 @@ static int md_open(struct inode *inode, struct file *file)
err = 0;
mddev_get(mddev);
+ atomic_inc(&mddev->openers);
mddev_unlock(mddev);
check_disk_change(inode->i_bdev);
@@ -4895,6 +5033,7 @@ static int md_release(struct inode *inode, struct file * file)
mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
BUG_ON(!mddev);
+ atomic_dec(&mddev->openers);
mddev_put(mddev);
return 0;
@@ -5029,6 +5168,9 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
if (!mddev->pers->error_handler)
return;
mddev->pers->error_handler(mddev,rdev);
+ if (mddev->degraded)
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+ set_bit(StateChanged, &rdev->flags);
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
@@ -5258,10 +5400,11 @@ static int md_seq_show(struct seq_file *seq, void *v)
if (!list_empty(&mddev->disks)) {
if (mddev->pers)
seq_printf(seq, "\n %llu blocks",
- (unsigned long long)mddev->array_size);
+ (unsigned long long)
+ mddev->array_sectors / 2);
else
seq_printf(seq, "\n %llu blocks",
- (unsigned long long)size);
+ (unsigned long long)size);
}
if (mddev->persistent) {
if (mddev->major_version != 0 ||
@@ -5391,12 +5534,12 @@ int unregister_md_personality(struct mdk_personality *p)
static int is_mddev_idle(mddev_t *mddev)
{
mdk_rdev_t * rdev;
- struct list_head *tmp;
int idle;
long curr_events;
idle = 1;
- rdev_for_each(rdev, tmp, mddev) {
+ rcu_read_lock();
+ rdev_for_each_rcu(rdev, mddev) {
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
curr_events = disk_stat_read(disk, sectors[0]) +
disk_stat_read(disk, sectors[1]) -
@@ -5428,6 +5571,7 @@ static int is_mddev_idle(mddev_t *mddev)
idle = 0;
}
}
+ rcu_read_unlock();
return idle;
}
@@ -5451,6 +5595,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
*/
void md_write_start(mddev_t *mddev, struct bio *bi)
{
+ int did_change = 0;
if (bio_data_dir(bi) != WRITE)
return;
@@ -5461,6 +5606,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
md_wakeup_thread(mddev->sync_thread);
+ did_change = 1;
}
atomic_inc(&mddev->writes_pending);
if (mddev->safemode == 1)
@@ -5471,10 +5617,12 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
mddev->in_sync = 0;
set_bit(MD_CHANGE_CLEAN, &mddev->flags);
md_wakeup_thread(mddev->thread);
+ did_change = 1;
}
spin_unlock_irq(&mddev->write_lock);
- sysfs_notify(&mddev->kobj, NULL, "array_state");
}
+ if (did_change)
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
wait_event(mddev->sb_wait,
!test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
!test_bit(MD_CHANGE_PENDING, &mddev->flags));
@@ -5495,13 +5643,18 @@ void md_write_end(mddev_t *mddev)
* may proceed without blocking. It is important to call this before
* attempting a GFP_KERNEL allocation while holding the mddev lock.
* Must be called with mddev_lock held.
+ *
+ * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
+ * is dropped, so return -EAGAIN after notifying userspace.
*/
-void md_allow_write(mddev_t *mddev)
+int md_allow_write(mddev_t *mddev)
{
if (!mddev->pers)
- return;
+ return 0;
if (mddev->ro)
- return;
+ return 0;
+ if (!mddev->pers->sync_request)
+ return 0;
spin_lock_irq(&mddev->write_lock);
if (mddev->in_sync) {
@@ -5512,14 +5665,14 @@ void md_allow_write(mddev_t *mddev)
mddev->safemode = 1;
spin_unlock_irq(&mddev->write_lock);
md_update_sb(mddev, 0);
-
sysfs_notify(&mddev->kobj, NULL, "array_state");
- /* wait for the dirty state to be recorded in the metadata */
- wait_event(mddev->sb_wait,
- !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
- !test_bit(MD_CHANGE_PENDING, &mddev->flags));
} else
spin_unlock_irq(&mddev->write_lock);
+
+ if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
+ return -EAGAIN;
+ else
+ return 0;
}
EXPORT_SYMBOL_GPL(md_allow_write);
@@ -5625,9 +5778,11 @@ void md_do_sync(mddev_t *mddev)
max_sectors = mddev->resync_max_sectors;
mddev->resync_mismatches = 0;
/* we don't use the checkpoint if there's a bitmap */
- if (!mddev->bitmap &&
- !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+ j = mddev->resync_min;
+ else if (!mddev->bitmap)
j = mddev->recovery_cp;
+
} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
max_sectors = mddev->size << 1;
else {
@@ -5796,6 +5951,7 @@ void md_do_sync(mddev_t *mddev)
skip:
mddev->curr_resync = 0;
+ mddev->resync_min = 0;
mddev->resync_max = MaxSector;
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
wake_up(&resync_wait);
@@ -5845,7 +6001,8 @@ static int remove_and_add_spares(mddev_t *mddev)
if (rdev->raid_disk < 0
&& !test_bit(Faulty, &rdev->flags)) {
rdev->recovery_offset = 0;
- if (mddev->pers->hot_add_disk(mddev,rdev)) {
+ if (mddev->pers->
+ hot_add_disk(mddev, rdev) == 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
if (sysfs_create_link(&mddev->kobj,
@@ -5920,23 +6077,31 @@ void md_check_recovery(mddev_t *mddev)
int spares = 0;
if (!mddev->external) {
+ int did_change = 0;
spin_lock_irq(&mddev->write_lock);
if (mddev->safemode &&
!atomic_read(&mddev->writes_pending) &&
!mddev->in_sync &&
mddev->recovery_cp == MaxSector) {
mddev->in_sync = 1;
+ did_change = 1;
if (mddev->persistent)
set_bit(MD_CHANGE_CLEAN, &mddev->flags);
}
if (mddev->safemode == 1)
mddev->safemode = 0;
spin_unlock_irq(&mddev->write_lock);
+ if (did_change)
+ sysfs_notify(&mddev->kobj, NULL, "array_state");
}
if (mddev->flags)
md_update_sb(mddev, 0);
+ rdev_for_each(rdev, rtmp, mddev)
+ if (test_and_clear_bit(StateChanged, &rdev->flags))
+ sysfs_notify(&rdev->kobj, NULL, "state");
+
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
@@ -5951,7 +6116,9 @@ void md_check_recovery(mddev_t *mddev)
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
/* success...*/
/* activate any spares */
- mddev->pers->spare_active(mddev);
+ if (mddev->pers->spare_active(mddev))
+ sysfs_notify(&mddev->kobj, NULL,
+ "degraded");
}
md_update_sb(mddev, 1);
@@ -5965,13 +6132,18 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
md_new_event(mddev);
goto unlock;
}
+ /* Set RUNNING before clearing NEEDED to avoid
+ * any transients in the value of "sync_action".
+ */
+ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
/* Clear some bits that don't mean anything, but
* might be left set
*/
- clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
@@ -5989,17 +6161,19 @@ void md_check_recovery(mddev_t *mddev)
/* Cannot proceed */
goto unlock;
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+ clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
} else if ((spares = remove_and_add_spares(mddev))) {
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
} else if (mddev->recovery_cp < MaxSector) {
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
} else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
/* nothing to be done ... */
goto unlock;
if (mddev->pers->sync_request) {
- set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
if (spares && mddev->bitmap && ! mddev->bitmap->file) {
/* We are adding a device or devices to an array
* which has the bitmap stored on all devices.
@@ -6018,9 +6192,16 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
} else
md_wakeup_thread(mddev->sync_thread);
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
md_new_event(mddev);
}
unlock:
+ if (!mddev->sync_thread) {
+ clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+ if (test_and_clear_bit(MD_RECOVERY_RECOVER,
+ &mddev->recovery))
+ sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ }
mddev_unlock(mddev);
}
}
@@ -6047,7 +6228,7 @@ static int md_notify_reboot(struct notifier_block *this,
for_each_mddev(mddev, tmp)
if (mddev_trylock(mddev)) {
- do_md_stop (mddev, 1);
+ do_md_stop (mddev, 1, 0);
mddev_unlock(mddev);
}
/*
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e968116e0de..c4779ccba1c 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -281,13 +281,18 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
multipath_conf_t *conf = mddev->private;
struct request_queue *q;
- int found = 0;
+ int err = -EEXIST;
int path;
struct multipath_info *p;
+ int first = 0;
+ int last = mddev->raid_disks - 1;
+
+ if (rdev->raid_disk >= 0)
+ first = last = rdev->raid_disk;
print_multipath_conf(conf);
- for (path=0; path<mddev->raid_disks; path++)
+ for (path = first; path <= last; path++)
if ((p=conf->multipaths+path)->rdev == NULL) {
q = rdev->bdev->bd_disk->queue;
blk_queue_stack_limits(mddev->queue, q);
@@ -307,11 +312,13 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->raid_disk = path;
set_bit(In_sync, &rdev->flags);
rcu_assign_pointer(p->rdev, rdev);
- found = 1;
+ err = 0;
+ break;
}
print_multipath_conf(conf);
- return found;
+
+ return err;
}
static int multipath_remove_disk(mddev_t *mddev, int number)
@@ -497,7 +504,7 @@ static int multipath_run (mddev_t *mddev)
/*
* Ok, everything is just fine now
*/
- mddev->array_size = mddev->size;
+ mddev->array_sectors = mddev->size * 2;
mddev->queue->unplug_fn = multipath_unplug;
mddev->queue->backing_dev_info.congested_fn = multipath_congested;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index bcbb82594a1..18361063566 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -295,16 +295,16 @@ static int raid0_run (mddev_t *mddev)
goto out_free_conf;
/* calculate array device size */
- mddev->array_size = 0;
+ mddev->array_sectors = 0;
rdev_for_each(rdev, tmp, mddev)
- mddev->array_size += rdev->size;
+ mddev->array_sectors += rdev->size * 2;
printk("raid0 : md_size is %llu blocks.\n",
- (unsigned long long)mddev->array_size);
+ (unsigned long long)mddev->array_sectors / 2);
printk("raid0 : conf->hash_spacing is %llu blocks.\n",
(unsigned long long)conf->hash_spacing);
{
- sector_t s = mddev->array_size;
+ sector_t s = mddev->array_sectors / 2;
sector_t space = conf->hash_spacing;
int round;
conf->preshift = 0;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index c610b947218..03a5ab705c2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1100,11 +1100,16 @@ static int raid1_spare_active(mddev_t *mddev)
static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
conf_t *conf = mddev->private;
- int found = 0;
+ int err = -EEXIST;
int mirror = 0;
mirror_info_t *p;
+ int first = 0;
+ int last = mddev->raid_disks - 1;
- for (mirror=0; mirror < mddev->raid_disks; mirror++)
+ if (rdev->raid_disk >= 0)
+ first = last = rdev->raid_disk;
+
+ for (mirror = first; mirror <= last; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
blk_queue_stack_limits(mddev->queue,
@@ -1119,7 +1124,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
- found = 1;
+ err = 0;
/* As all devices are equivalent, we don't need a full recovery
* if this was recently any drive of the array
*/
@@ -1130,7 +1135,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
}
print_conf(conf);
- return found;
+ return err;
}
static int raid1_remove_disk(mddev_t *mddev, int number)
@@ -2038,7 +2043,7 @@ static int run(mddev_t *mddev)
/*
* Ok, everything is just fine now
*/
- mddev->array_size = mddev->size;
+ mddev->array_sectors = mddev->size * 2;
mddev->queue->unplug_fn = raid1_unplug;
mddev->queue->backing_dev_info.congested_fn = raid1_congested;
@@ -2100,14 +2105,15 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
* any io in the removed space completes, but it hardly seems
* worth it.
*/
- mddev->array_size = sectors>>1;
- set_capacity(mddev->gendisk, mddev->array_size << 1);
+ mddev->array_sectors = sectors;
+ set_capacity(mddev->gendisk, mddev->array_sectors);
mddev->changed = 1;
- if (mddev->array_size > mddev->size && mddev->recovery_cp == MaxSector) {
+ if (mddev->array_sectors / 2 > mddev->size &&
+ mddev->recovery_cp == MaxSector) {
mddev->recovery_cp = mddev->size << 1;
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
}
- mddev->size = mddev->array_size;
+ mddev->size = mddev->array_sectors / 2;
mddev->resync_max_sectors = sectors;
return 0;
}
@@ -2131,7 +2137,7 @@ static int raid1_reshape(mddev_t *mddev)
conf_t *conf = mddev_to_conf(mddev);
int cnt, raid_disks;
unsigned long flags;
- int d, d2;
+ int d, d2, err;
/* Cannot change chunk_size, layout, or level */
if (mddev->chunk_size != mddev->new_chunk ||
@@ -2143,7 +2149,9 @@ static int raid1_reshape(mddev_t *mddev)
return -EINVAL;
}
- md_allow_write(mddev);
+ err = md_allow_write(mddev);
+ if (err)
+ return err;
raid_disks = mddev->raid_disks + mddev->delta_disks;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 22bb2b1b886..159535d7356 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1114,24 +1114,30 @@ static int raid10_spare_active(mddev_t *mddev)
static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
conf_t *conf = mddev->private;
- int found = 0;
+ int err = -EEXIST;
int mirror;
mirror_info_t *p;
+ int first = 0;
+ int last = mddev->raid_disks - 1;
if (mddev->recovery_cp < MaxSector)
/* only hot-add to in-sync arrays, as recovery is
* very different from resync
*/
- return 0;
+ return -EBUSY;
if (!enough(conf))
- return 0;
+ return -EINVAL;
+
+ if (rdev->raid_disk)
+ first = last = rdev->raid_disk;
if (rdev->saved_raid_disk >= 0 &&
+ rdev->saved_raid_disk >= first &&
conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
mirror = rdev->saved_raid_disk;
else
- mirror = 0;
- for ( ; mirror < mddev->raid_disks; mirror++)
+ mirror = first;
+ for ( ; mirror <= last ; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
blk_queue_stack_limits(mddev->queue,
@@ -1146,7 +1152,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
- found = 1;
+ err = 0;
if (rdev->saved_raid_disk != mirror)
conf->fullsync = 1;
rcu_assign_pointer(p->rdev, rdev);
@@ -1154,7 +1160,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
}
print_conf(conf);
- return found;
+ return err;
}
static int raid10_remove_disk(mddev_t *mddev, int number)
@@ -2159,7 +2165,7 @@ static int run(mddev_t *mddev)
/*
* Ok, everything is just fine now
*/
- mddev->array_size = size << (conf->chunk_shift-1);
+ mddev->array_sectors = size << conf->chunk_shift;
mddev->resync_max_sectors = size << conf->chunk_shift;
mddev->queue->unplug_fn = raid10_unplug;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9ce7154845c..55e7c56045a 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -115,15 +115,20 @@ static void return_io(struct bio *return_bi)
return_bi = bi->bi_next;
bi->bi_next = NULL;
bi->bi_size = 0;
- bi->bi_end_io(bi,
- test_bit(BIO_UPTODATE, &bi->bi_flags)
- ? 0 : -EIO);
+ bio_endio(bi, 0);
bi = return_bi;
}
}
static void print_raid5_conf (raid5_conf_t *conf);
+static int stripe_operations_active(struct stripe_head *sh)
+{
+ return sh->check_state || sh->reconstruct_state ||
+ test_bit(STRIPE_BIOFILL_RUN, &sh->state) ||
+ test_bit(STRIPE_COMPUTE_RUN, &sh->state);
+}
+
static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
@@ -143,7 +148,7 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
}
md_wakeup_thread(conf->mddev->thread);
} else {
- BUG_ON(sh->ops.pending);
+ BUG_ON(stripe_operations_active(sh));
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
atomic_dec(&conf->preread_active_stripes);
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -245,7 +250,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
BUG_ON(atomic_read(&sh->count) != 0);
BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
- BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+ BUG_ON(stripe_operations_active(sh));
CHECK_DEVLOCK();
pr_debug("init_stripe called, stripe %llu\n",
@@ -346,62 +351,18 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
return sh;
}
-/* test_and_ack_op() ensures that we only dequeue an operation once */
-#define test_and_ack_op(op, pend) \
-do { \
- if (test_bit(op, &sh->ops.pending) && \
- !test_bit(op, &sh->ops.complete)) { \
- if (test_and_set_bit(op, &sh->ops.ack)) \
- clear_bit(op, &pend); \
- else \
- ack++; \
- } else \
- clear_bit(op, &pend); \
-} while (0)
-
-/* find new work to run, do not resubmit work that is already
- * in flight
- */
-static unsigned long get_stripe_work(struct stripe_head *sh)
-{
- unsigned long pending;
- int ack = 0;
-
- pending = sh->ops.pending;
-
- test_and_ack_op(STRIPE_OP_BIOFILL, pending);
- test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
- test_and_ack_op(STRIPE_OP_PREXOR, pending);
- test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
- test_and_ack_op(STRIPE_OP_POSTXOR, pending);
- test_and_ack_op(STRIPE_OP_CHECK, pending);
- if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
- ack++;
-
- sh->ops.count -= ack;
- if (unlikely(sh->ops.count < 0)) {
- printk(KERN_ERR "pending: %#lx ops.pending: %#lx ops.ack: %#lx "
- "ops.complete: %#lx\n", pending, sh->ops.pending,
- sh->ops.ack, sh->ops.complete);
- BUG();
- }
-
- return pending;
-}
-
static void
raid5_end_read_request(struct bio *bi, int error);
static void
raid5_end_write_request(struct bio *bi, int error);
-static void ops_run_io(struct stripe_head *sh)
+static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
{
raid5_conf_t *conf = sh->raid_conf;
int i, disks = sh->disks;
might_sleep();
- set_bit(STRIPE_IO_STARTED, &sh->state);
for (i = disks; i--; ) {
int rw;
struct bio *bi;
@@ -430,11 +391,11 @@ static void ops_run_io(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (test_bit(STRIPE_SYNCING, &sh->state) ||
- test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
- test_bit(STRIPE_EXPAND_READY, &sh->state))
+ if (s->syncing || s->expanding || s->expanded)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+ set_bit(STRIPE_IO_STARTED, &sh->state);
+
bi->bi_bdev = rdev->bdev;
pr_debug("%s: for %llu schedule op %ld on disc %d\n",
__func__, (unsigned long long)sh->sector,
@@ -528,38 +489,34 @@ static void ops_complete_biofill(void *stripe_head_ref)
(unsigned long long)sh->sector);
/* clear completed biofills */
+ spin_lock_irq(&conf->device_lock);
for (i = sh->disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
/* acknowledge completion of a biofill operation */
/* and check if we need to reply to a read request,
* new R5_Wantfill requests are held off until
- * !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending)
+ * !STRIPE_BIOFILL_RUN
*/
if (test_and_clear_bit(R5_Wantfill, &dev->flags)) {
struct bio *rbi, *rbi2;
- /* The access to dev->read is outside of the
- * spin_lock_irq(&conf->device_lock), but is protected
- * by the STRIPE_OP_BIOFILL pending bit
- */
BUG_ON(!dev->read);
rbi = dev->read;
dev->read = NULL;
while (rbi && rbi->bi_sector <
dev->sector + STRIPE_SECTORS) {
rbi2 = r5_next_bio(rbi, dev->sector);
- spin_lock_irq(&conf->device_lock);
if (--rbi->bi_phys_segments == 0) {
rbi->bi_next = return_bi;
return_bi = rbi;
}
- spin_unlock_irq(&conf->device_lock);
rbi = rbi2;
}
}
}
- set_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
+ spin_unlock_irq(&conf->device_lock);
+ clear_bit(STRIPE_BIOFILL_RUN, &sh->state);
return_io(return_bi);
@@ -610,13 +567,14 @@ static void ops_complete_compute5(void *stripe_head_ref)
set_bit(R5_UPTODATE, &tgt->flags);
BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
clear_bit(R5_Wantcompute, &tgt->flags);
- set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+ clear_bit(STRIPE_COMPUTE_RUN, &sh->state);
+ if (sh->check_state == check_state_compute_run)
+ sh->check_state = check_state_compute_result;
set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
}
-static struct dma_async_tx_descriptor *
-ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+static struct dma_async_tx_descriptor *ops_run_compute5(struct stripe_head *sh)
{
/* kernel stack size limits the total number of disks */
int disks = sh->disks;
@@ -646,10 +604,6 @@ ops_run_compute5(struct stripe_head *sh, unsigned long pending)
ASYNC_TX_XOR_ZERO_DST, NULL,
ops_complete_compute5, sh);
- /* ack now if postxor is not set to be run */
- if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
- async_tx_ack(tx);
-
return tx;
}
@@ -659,8 +613,6 @@ static void ops_complete_prexor(void *stripe_head_ref)
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
-
- set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
}
static struct dma_async_tx_descriptor *
@@ -680,7 +632,7 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
/* Only process blocks that are known to be uptodate */
- if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+ if (test_bit(R5_Wantdrain, &dev->flags))
xor_srcs[count++] = dev->page;
}
@@ -692,16 +644,10 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
}
static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
- unsigned long pending)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
{
int disks = sh->disks;
- int pd_idx = sh->pd_idx, i;
-
- /* check if prexor is active which means only process blocks
- * that are part of a read-modify-write (Wantprexor)
- */
- int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
+ int i;
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
@@ -709,20 +655,8 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
struct bio *chosen;
- int towrite;
-
- towrite = 0;
- if (prexor) { /* rmw */
- if (dev->towrite &&
- test_bit(R5_Wantprexor, &dev->flags))
- towrite = 1;
- } else { /* rcw */
- if (i != pd_idx && dev->towrite &&
- test_bit(R5_LOCKED, &dev->flags))
- towrite = 1;
- }
- if (towrite) {
+ if (test_and_clear_bit(R5_Wantdrain, &dev->flags)) {
struct bio *wbi;
spin_lock(&sh->lock);
@@ -747,18 +681,6 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
static void ops_complete_postxor(void *stripe_head_ref)
{
struct stripe_head *sh = stripe_head_ref;
-
- pr_debug("%s: stripe %llu\n", __func__,
- (unsigned long long)sh->sector);
-
- set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
- set_bit(STRIPE_HANDLE, &sh->state);
- release_stripe(sh);
-}
-
-static void ops_complete_write(void *stripe_head_ref)
-{
- struct stripe_head *sh = stripe_head_ref;
int disks = sh->disks, i, pd_idx = sh->pd_idx;
pr_debug("%s: stripe %llu\n", __func__,
@@ -770,16 +692,21 @@ static void ops_complete_write(void *stripe_head_ref)
set_bit(R5_UPTODATE, &dev->flags);
}
- set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
- set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+ if (sh->reconstruct_state == reconstruct_state_drain_run)
+ sh->reconstruct_state = reconstruct_state_drain_result;
+ else if (sh->reconstruct_state == reconstruct_state_prexor_drain_run)
+ sh->reconstruct_state = reconstruct_state_prexor_drain_result;
+ else {
+ BUG_ON(sh->reconstruct_state != reconstruct_state_run);
+ sh->reconstruct_state = reconstruct_state_result;
+ }
set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
}
static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
- unsigned long pending)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
{
/* kernel stack size limits the total number of disks */
int disks = sh->disks;
@@ -787,9 +714,8 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
int count = 0, pd_idx = sh->pd_idx, i;
struct page *xor_dest;
- int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
+ int prexor = 0;
unsigned long flags;
- dma_async_tx_callback callback;
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
@@ -797,7 +723,8 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
/* check if prexor is active which means only process blocks
* that are part of a read-modify-write (written)
*/
- if (prexor) {
+ if (sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
+ prexor = 1;
xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
@@ -813,10 +740,6 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
}
}
- /* check whether this postxor is part of a write */
- callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
- ops_complete_write : ops_complete_postxor;
-
/* 1/ if we prexor'd then the dest is reused as a source
* 2/ if we did not prexor then we are redoing the parity
* set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
@@ -830,25 +753,20 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
if (unlikely(count == 1)) {
flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
- flags, tx, callback, sh);
+ flags, tx, ops_complete_postxor, sh);
} else
tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
- flags, tx, callback, sh);
+ flags, tx, ops_complete_postxor, sh);
}
static void ops_complete_check(void *stripe_head_ref)
{
struct stripe_head *sh = stripe_head_ref;
- int pd_idx = sh->pd_idx;
pr_debug("%s: stripe %llu\n", __func__,
(unsigned long long)sh->sector);
- if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
- sh->ops.zero_sum_result == 0)
- set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-
- set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+ sh->check_state = check_state_check_result;
set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
}
@@ -875,46 +793,42 @@ static void ops_run_check(struct stripe_head *sh)
tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
&sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
- if (tx)
- set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
- else
- clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
-
atomic_inc(&sh->count);
tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
ops_complete_check, sh);
}
-static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+static void raid5_run_ops(struct stripe_head *sh, unsigned long ops_request)
{
int overlap_clear = 0, i, disks = sh->disks;
struct dma_async_tx_descriptor *tx = NULL;
- if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+ if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {
ops_run_biofill(sh);
overlap_clear++;
}
- if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
- tx = ops_run_compute5(sh, pending);
+ if (test_bit(STRIPE_OP_COMPUTE_BLK, &ops_request)) {
+ tx = ops_run_compute5(sh);
+ /* terminate the chain if postxor is not set to be run */
+ if (tx && !test_bit(STRIPE_OP_POSTXOR, &ops_request))
+ async_tx_ack(tx);
+ }
- if (test_bit(STRIPE_OP_PREXOR, &pending))
+ if (test_bit(STRIPE_OP_PREXOR, &ops_request))
tx = ops_run_prexor(sh, tx);
- if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
- tx = ops_run_biodrain(sh, tx, pending);
+ if (test_bit(STRIPE_OP_BIODRAIN, &ops_request)) {
+ tx = ops_run_biodrain(sh, tx);
overlap_clear++;
}
- if (test_bit(STRIPE_OP_POSTXOR, &pending))
- ops_run_postxor(sh, tx, pending);
+ if (test_bit(STRIPE_OP_POSTXOR, &ops_request))
+ ops_run_postxor(sh, tx);
- if (test_bit(STRIPE_OP_CHECK, &pending))
+ if (test_bit(STRIPE_OP_CHECK, &ops_request))
ops_run_check(sh);
- if (test_bit(STRIPE_OP_IO, &pending))
- ops_run_io(sh);
-
if (overlap_clear)
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
@@ -997,14 +911,16 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
struct stripe_head *osh, *nsh;
LIST_HEAD(newstripes);
struct disk_info *ndisks;
- int err = 0;
+ int err;
struct kmem_cache *sc;
int i;
if (newsize <= conf->pool_size)
return 0; /* never bother to shrink */
- md_allow_write(conf->mddev);
+ err = md_allow_write(conf->mddev);
+ if (err)
+ return err;
/* Step 1 */
sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
@@ -1703,11 +1619,11 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
}
}
-static int
-handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+static void
+schedule_reconstruction5(struct stripe_head *sh, struct stripe_head_state *s,
+ int rcw, int expand)
{
int i, pd_idx = sh->pd_idx, disks = sh->disks;
- int locked = 0;
if (rcw) {
/* if we are not expanding this is a proper write request, and
@@ -1715,53 +1631,48 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
* stripe cache
*/
if (!expand) {
- set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
- sh->ops.count++;
- }
+ sh->reconstruct_state = reconstruct_state_drain_run;
+ set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+ } else
+ sh->reconstruct_state = reconstruct_state_run;
- set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
- sh->ops.count++;
+ set_bit(STRIPE_OP_POSTXOR, &s->ops_request);
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
if (dev->towrite) {
set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantdrain, &dev->flags);
if (!expand)
clear_bit(R5_UPTODATE, &dev->flags);
- locked++;
+ s->locked++;
}
}
- if (locked + 1 == disks)
+ if (s->locked + 1 == disks)
if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
atomic_inc(&sh->raid_conf->pending_full_writes);
} else {
BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
- set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
- set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
- set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-
- sh->ops.count += 3;
+ sh->reconstruct_state = reconstruct_state_prexor_drain_run;
+ set_bit(STRIPE_OP_PREXOR, &s->ops_request);
+ set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+ set_bit(STRIPE_OP_POSTXOR, &s->ops_request);
for (i = disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
if (i == pd_idx)
continue;
- /* For a read-modify write there may be blocks that are
- * locked for reading while others are ready to be
- * written so we distinguish these blocks by the
- * R5_Wantprexor bit
- */
if (dev->towrite &&
(test_bit(R5_UPTODATE, &dev->flags) ||
- test_bit(R5_Wantcompute, &dev->flags))) {
- set_bit(R5_Wantprexor, &dev->flags);
+ test_bit(R5_Wantcompute, &dev->flags))) {
+ set_bit(R5_Wantdrain, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
clear_bit(R5_UPTODATE, &dev->flags);
- locked++;
+ s->locked++;
}
}
}
@@ -1771,13 +1682,11 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
*/
set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
- locked++;
+ s->locked++;
- pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+ pr_debug("%s: stripe %llu locked: %d ops_request: %lx\n",
__func__, (unsigned long long)sh->sector,
- locked, sh->ops.pending);
-
- return locked;
+ s->locked, s->ops_request);
}
/*
@@ -1876,7 +1785,7 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
}
static void
-handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
struct stripe_head_state *s, int disks,
struct bio **return_bi)
{
@@ -1967,48 +1876,38 @@ handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
md_wakeup_thread(conf->mddev->thread);
}
-/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
- * to process
+/* fetch_block5 - checks the given member device to see if its data needs
+ * to be read or computed to satisfy a request.
+ *
+ * Returns 1 when no more member devices need to be checked, otherwise returns
+ * 0 to tell the loop in handle_stripe_fill5 to continue
*/
-static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
- struct stripe_head_state *s, int disk_idx, int disks)
+static int fetch_block5(struct stripe_head *sh, struct stripe_head_state *s,
+ int disk_idx, int disks)
{
struct r5dev *dev = &sh->dev[disk_idx];
struct r5dev *failed_dev = &sh->dev[s->failed_num];
- /* don't schedule compute operations or reads on the parity block while
- * a check is in flight
- */
- if ((disk_idx == sh->pd_idx) &&
- test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
- return ~0;
-
/* is the data in this block needed, and can we get it? */
if (!test_bit(R5_LOCKED, &dev->flags) &&
- !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
- (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
- s->syncing || s->expanding || (s->failed &&
- (failed_dev->toread || (failed_dev->towrite &&
- !test_bit(R5_OVERWRITE, &failed_dev->flags)
- ))))) {
- /* 1/ We would like to get this block, possibly by computing it,
- * but we might not be able to.
- *
- * 2/ Since parity check operations potentially make the parity
- * block !uptodate it will need to be refreshed before any
- * compute operations on data disks are scheduled.
- *
- * 3/ We hold off parity block re-reads until check operations
- * have quiesced.
+ !test_bit(R5_UPTODATE, &dev->flags) &&
+ (dev->toread ||
+ (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+ s->syncing || s->expanding ||
+ (s->failed &&
+ (failed_dev->toread ||
+ (failed_dev->towrite &&
+ !test_bit(R5_OVERWRITE, &failed_dev->flags)))))) {
+ /* We would like to get this block, possibly by computing it,
+ * otherwise read it if the backing disk is insync
*/
if ((s->uptodate == disks - 1) &&
- (s->failed && disk_idx == s->failed_num) &&
- !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
- set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+ (s->failed && disk_idx == s->failed_num)) {
+ set_bit(STRIPE_COMPUTE_RUN, &sh->state);
+ set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
set_bit(R5_Wantcompute, &dev->flags);
sh->ops.target = disk_idx;
s->req_compute = 1;
- sh->ops.count++;
/* Careful: from this point on 'uptodate' is in the eye
* of raid5_run_ops which services 'compute' operations
* before writes. R5_Wantcompute flags a block that will
@@ -2016,53 +1915,40 @@ static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
* subsequent operation.
*/
s->uptodate++;
- return 0; /* uptodate + compute == disks */
+ return 1; /* uptodate + compute == disks */
} else if (test_bit(R5_Insync, &dev->flags)) {
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantread, &dev->flags);
- if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
s->locked++;
pr_debug("Reading block %d (sync=%d)\n", disk_idx,
s->syncing);
}
}
- return ~0;
+ return 0;
}
-static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+/**
+ * handle_stripe_fill5 - read or compute data to satisfy pending requests.
+ */
+static void handle_stripe_fill5(struct stripe_head *sh,
struct stripe_head_state *s, int disks)
{
int i;
- /* Clear completed compute operations. Parity recovery
- * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
- * later on in this routine
- */
- if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
- !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
- }
-
/* look for blocks to read/compute, skip this if a compute
* is already in flight, or if the stripe contents are in the
* midst of changing due to a write
*/
- if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
- !test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
- !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+ if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
+ !sh->reconstruct_state)
for (i = disks; i--; )
- if (__handle_issuing_new_read_requests5(
- sh, s, i, disks) == 0)
+ if (fetch_block5(sh, s, i, disks))
break;
- }
set_bit(STRIPE_HANDLE, &sh->state);
}
-static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+static void handle_stripe_fill6(struct stripe_head *sh,
struct stripe_head_state *s, struct r6_state *r6s,
int disks)
{
@@ -2121,12 +2007,12 @@ static void handle_issuing_new_read_requests6(struct stripe_head *sh,
}
-/* handle_completed_write_requests
+/* handle_stripe_clean_event
* any written block on an uptodate or failed drive can be returned.
* Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
* never LOCKED, so we don't need to test 'failed' directly.
*/
-static void handle_completed_write_requests(raid5_conf_t *conf,
+static void handle_stripe_clean_event(raid5_conf_t *conf,
struct stripe_head *sh, int disks, struct bio **return_bi)
{
int i;
@@ -2171,7 +2057,7 @@ static void handle_completed_write_requests(raid5_conf_t *conf,
md_wakeup_thread(conf->mddev->thread);
}
-static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+static void handle_stripe_dirtying5(raid5_conf_t *conf,
struct stripe_head *sh, struct stripe_head_state *s, int disks)
{
int rmw = 0, rcw = 0, i;
@@ -2215,9 +2101,6 @@ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
"%d for r-m-w\n", i);
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantread, &dev->flags);
- if (!test_and_set_bit(
- STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
s->locked++;
} else {
set_bit(STRIPE_DELAYED, &sh->state);
@@ -2241,9 +2124,6 @@ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
"%d for Reconstruct\n", i);
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantread, &dev->flags);
- if (!test_and_set_bit(
- STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
s->locked++;
} else {
set_bit(STRIPE_DELAYED, &sh->state);
@@ -2261,14 +2141,13 @@ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
* simultaneously. If this is not the case then new writes need to be
* held off until the compute completes.
*/
- if ((s->req_compute ||
- !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
- (s->locked == 0 && (rcw == 0 || rmw == 0) &&
- !test_bit(STRIPE_BIT_DELAY, &sh->state)))
- s->locked += handle_write_operations5(sh, rcw == 0, 0);
+ if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&
+ (s->locked == 0 && (rcw == 0 || rmw == 0) &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+ schedule_reconstruction5(sh, s, rcw == 0, 0);
}
-static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+static void handle_stripe_dirtying6(raid5_conf_t *conf,
struct stripe_head *sh, struct stripe_head_state *s,
struct r6_state *r6s, int disks)
{
@@ -2371,92 +2250,86 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
struct stripe_head_state *s, int disks)
{
- int canceled_check = 0;
+ struct r5dev *dev = NULL;
set_bit(STRIPE_HANDLE, &sh->state);
- /* complete a check operation */
- if (test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
- clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
- clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+ switch (sh->check_state) {
+ case check_state_idle:
+ /* start a new check operation if there are no failures */
if (s->failed == 0) {
- if (sh->ops.zero_sum_result == 0)
- /* parity is correct (on disc,
- * not in buffer any more)
- */
- set_bit(STRIPE_INSYNC, &sh->state);
- else {
- conf->mddev->resync_mismatches +=
- STRIPE_SECTORS;
- if (test_bit(
- MD_RECOVERY_CHECK, &conf->mddev->recovery))
- /* don't try to repair!! */
- set_bit(STRIPE_INSYNC, &sh->state);
- else {
- set_bit(STRIPE_OP_COMPUTE_BLK,
- &sh->ops.pending);
- set_bit(STRIPE_OP_MOD_REPAIR_PD,
- &sh->ops.pending);
- set_bit(R5_Wantcompute,
- &sh->dev[sh->pd_idx].flags);
- sh->ops.target = sh->pd_idx;
- sh->ops.count++;
- s->uptodate++;
- }
- }
- } else
- canceled_check = 1; /* STRIPE_INSYNC is not set */
- }
-
- /* start a new check operation if there are no failures, the stripe is
- * not insync, and a repair is not in flight
- */
- if (s->failed == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state) &&
- !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
- if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
BUG_ON(s->uptodate != disks);
+ sh->check_state = check_state_run;
+ set_bit(STRIPE_OP_CHECK, &s->ops_request);
clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
- sh->ops.count++;
s->uptodate--;
+ break;
}
- }
-
- /* check if we can clear a parity disk reconstruct */
- if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
- test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-
- clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
- clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
- }
-
+ dev = &sh->dev[s->failed_num];
+ /* fall through */
+ case check_state_compute_result:
+ sh->check_state = check_state_idle;
+ if (!dev)
+ dev = &sh->dev[sh->pd_idx];
+
+ /* check that a write has not made the stripe insync */
+ if (test_bit(STRIPE_INSYNC, &sh->state))
+ break;
- /* Wait for check parity and compute block operations to complete
- * before write-back. If a failure occurred while the check operation
- * was in flight we need to cycle this stripe through handle_stripe
- * since the parity block may not be uptodate
- */
- if (!canceled_check && !test_bit(STRIPE_INSYNC, &sh->state) &&
- !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
- !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
- struct r5dev *dev;
/* either failed parity check, or recovery is happening */
- if (s->failed == 0)
- s->failed_num = sh->pd_idx;
- dev = &sh->dev[s->failed_num];
BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
BUG_ON(s->uptodate != disks);
set_bit(R5_LOCKED, &dev->flags);
+ s->locked++;
set_bit(R5_Wantwrite, &dev->flags);
- if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
clear_bit(STRIPE_DEGRADED, &sh->state);
- s->locked++;
set_bit(STRIPE_INSYNC, &sh->state);
+ break;
+ case check_state_run:
+ break; /* we will be called again upon completion */
+ case check_state_check_result:
+ sh->check_state = check_state_idle;
+
+ /* if a failure occurred during the check operation, leave
+ * STRIPE_INSYNC not set and let the stripe be handled again
+ */
+ if (s->failed)
+ break;
+
+ /* handle a successful check operation, if parity is correct
+ * we are done. Otherwise update the mismatch count and repair
+ * parity if !MD_RECOVERY_CHECK
+ */
+ if (sh->ops.zero_sum_result == 0)
+ /* parity is correct (on disc,
+ * not in buffer any more)
+ */
+ set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ conf->mddev->resync_mismatches += STRIPE_SECTORS;
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ /* don't try to repair!! */
+ set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ sh->check_state = check_state_compute_run;
+ set_bit(STRIPE_COMPUTE_RUN, &sh->state);
+ set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
+ set_bit(R5_Wantcompute,
+ &sh->dev[sh->pd_idx].flags);
+ sh->ops.target = sh->pd_idx;
+ s->uptodate++;
+ }
+ }
+ break;
+ case check_state_compute_run:
+ break;
+ default:
+ printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n",
+ __func__, sh->check_state,
+ (unsigned long long) sh->sector);
+ BUG();
}
}
@@ -2641,15 +2514,14 @@ static void handle_stripe5(struct stripe_head *sh)
struct bio *return_bi = NULL;
struct stripe_head_state s;
struct r5dev *dev;
- unsigned long pending = 0;
mdk_rdev_t *blocked_rdev = NULL;
int prexor;
memset(&s, 0, sizeof(s));
- pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
- "ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
- atomic_read(&sh->count), sh->pd_idx,
- sh->ops.pending, sh->ops.ack, sh->ops.complete);
+ pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d check:%d "
+ "reconstruct:%d\n", (unsigned long long)sh->sector, sh->state,
+ atomic_read(&sh->count), sh->pd_idx, sh->check_state,
+ sh->reconstruct_state);
spin_lock(&sh->lock);
clear_bit(STRIPE_HANDLE, &sh->state);
@@ -2658,15 +2530,8 @@ static void handle_stripe5(struct stripe_head *sh)
s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
- /* Now to look around and see what can be done */
-
- /* clean-up completed biofill operations */
- if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) {
- clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
- clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
- clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
- }
+ /* Now to look around and see what can be done */
rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
@@ -2680,10 +2545,10 @@ static void handle_stripe5(struct stripe_head *sh)
/* maybe we can request a biofill operation
*
* new wantfill requests are only permitted while
- * STRIPE_OP_BIOFILL is clear
+ * ops_complete_biofill is guaranteed to be inactive
*/
if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
- !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+ !test_bit(STRIPE_BIOFILL_RUN, &sh->state))
set_bit(R5_Wantfill, &dev->flags);
/* now count some things */
@@ -2727,8 +2592,10 @@ static void handle_stripe5(struct stripe_head *sh)
goto unlock;
}
- if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
- sh->ops.count++;
+ if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
+ set_bit(STRIPE_OP_BIOFILL, &s.ops_request);
+ set_bit(STRIPE_BIOFILL_RUN, &sh->state);
+ }
pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d\n",
@@ -2738,8 +2605,7 @@ static void handle_stripe5(struct stripe_head *sh)
* need to be failed
*/
if (s.failed > 1 && s.to_read+s.to_write+s.written)
- handle_requests_to_failed_array(conf, sh, &s, disks,
- &return_bi);
+ handle_failed_stripe(conf, sh, &s, disks, &return_bi);
if (s.failed > 1 && s.syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
clear_bit(STRIPE_SYNCING, &sh->state);
@@ -2755,48 +2621,25 @@ static void handle_stripe5(struct stripe_head *sh)
!test_bit(R5_LOCKED, &dev->flags) &&
test_bit(R5_UPTODATE, &dev->flags)) ||
(s.failed == 1 && s.failed_num == sh->pd_idx)))
- handle_completed_write_requests(conf, sh, disks, &return_bi);
+ handle_stripe_clean_event(conf, sh, disks, &return_bi);
/* Now we might consider reading some blocks, either to check/generate
* parity, or to satisfy requests
* or to load a block that is being partially written.
*/
if (s.to_read || s.non_overwrite ||
- (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
- test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
- handle_issuing_new_read_requests5(sh, &s, disks);
+ (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding)
+ handle_stripe_fill5(sh, &s, disks);
/* Now we check to see if any write operations have recently
* completed
*/
-
- /* leave prexor set until postxor is done, allows us to distinguish
- * a rmw from a rcw during biodrain
- */
prexor = 0;
- if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
- test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-
+ if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
prexor = 1;
- clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
- clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
- clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-
- for (i = disks; i--; )
- clear_bit(R5_Wantprexor, &sh->dev[i].flags);
- }
-
- /* if only POSTXOR is set then this is an 'expand' postxor */
- if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
- test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-
- clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
- clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
- clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+ if (sh->reconstruct_state == reconstruct_state_drain_result ||
+ sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
+ sh->reconstruct_state = reconstruct_state_idle;
/* All the 'written' buffers and the parity block are ready to
* be written back to disk
@@ -2808,9 +2651,6 @@ static void handle_stripe5(struct stripe_head *sh)
(i == sh->pd_idx || dev->written)) {
pr_debug("Writing block %d\n", i);
set_bit(R5_Wantwrite, &dev->flags);
- if (!test_and_set_bit(
- STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
if (prexor)
continue;
if (!test_bit(R5_Insync, &dev->flags) ||
@@ -2832,20 +2672,18 @@ static void handle_stripe5(struct stripe_head *sh)
* 2/ A 'check' operation is in flight, as it may clobber the parity
* block.
*/
- if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
- !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
- handle_issuing_new_write_requests5(conf, sh, &s, disks);
+ if (s.to_write && !sh->reconstruct_state && !sh->check_state)
+ handle_stripe_dirtying5(conf, sh, &s, disks);
/* maybe we need to check and possibly fix the parity for this stripe
* Any reads will already have been scheduled, so we just see if enough
* data is available. The parity check is held off while parity
* dependent operations are in flight.
*/
- if ((s.syncing && s.locked == 0 &&
- !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
- !test_bit(STRIPE_INSYNC, &sh->state)) ||
- test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
- test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+ if (sh->check_state ||
+ (s.syncing && s.locked == 0 &&
+ !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
+ !test_bit(STRIPE_INSYNC, &sh->state)))
handle_parity_checks5(conf, sh, &s, disks);
if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
@@ -2864,52 +2702,35 @@ static void handle_stripe5(struct stripe_head *sh)
dev = &sh->dev[s.failed_num];
if (!test_bit(R5_ReWrite, &dev->flags)) {
set_bit(R5_Wantwrite, &dev->flags);
- if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
set_bit(R5_ReWrite, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
s.locked++;
} else {
/* let's read it back */
set_bit(R5_Wantread, &dev->flags);
- if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
set_bit(R5_LOCKED, &dev->flags);
s.locked++;
}
}
- /* Finish postxor operations initiated by the expansion
- * process
- */
- if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
- !test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
-
+ /* Finish reconstruct operations initiated by the expansion process */
+ if (sh->reconstruct_state == reconstruct_state_result) {
+ sh->reconstruct_state = reconstruct_state_idle;
clear_bit(STRIPE_EXPANDING, &sh->state);
-
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
- clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-
- for (i = conf->raid_disks; i--; ) {
+ for (i = conf->raid_disks; i--; )
set_bit(R5_Wantwrite, &sh->dev[i].flags);
set_bit(R5_LOCKED, &dev->flags);
s.locked++;
- if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
- }
}
if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
- !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+ !sh->reconstruct_state) {
/* Need to write out all blocks after computing parity */
sh->disks = conf->raid_disks;
sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
conf->raid_disks);
- s.locked += handle_write_operations5(sh, 1, 1);
- } else if (s.expanded &&
- s.locked == 0 &&
- !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+ schedule_reconstruction5(sh, &s, 1, 1);
+ } else if (s.expanded && !sh->reconstruct_state && s.locked == 0) {
clear_bit(STRIPE_EXPAND_READY, &sh->state);
atomic_dec(&conf->reshape_stripes);
wake_up(&conf->wait_for_overlap);
@@ -2917,12 +2738,9 @@ static void handle_stripe5(struct stripe_head *sh)
}
if (s.expanding && s.locked == 0 &&
- !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+ !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
handle_stripe_expansion(conf, sh, NULL);
- if (sh->ops.count)
- pending = get_stripe_work(sh);
-
unlock:
spin_unlock(&sh->lock);
@@ -2930,11 +2748,12 @@ static void handle_stripe5(struct stripe_head *sh)
if (unlikely(blocked_rdev))
md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
- if (pending)
- raid5_run_ops(sh, pending);
+ if (s.ops_request)
+ raid5_run_ops(sh, s.ops_request);
- return_io(return_bi);
+ ops_run_io(sh, &s);
+ return_io(return_bi);
}
static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
@@ -3042,8 +2861,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
* might need to be failed
*/
if (s.failed > 2 && s.to_read+s.to_write+s.written)
- handle_requests_to_failed_array(conf, sh, &s, disks,
- &return_bi);
+ handle_failed_stripe(conf, sh, &s, disks, &return_bi);
if (s.failed > 2 && s.syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
clear_bit(STRIPE_SYNCING, &sh->state);
@@ -3068,7 +2886,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
&& !test_bit(R5_LOCKED, &qdev->flags)
&& test_bit(R5_UPTODATE, &qdev->flags)))))
- handle_completed_write_requests(conf, sh, disks, &return_bi);
+ handle_stripe_clean_event(conf, sh, disks, &return_bi);
/* Now we might consider reading some blocks, either to check/generate
* parity, or to satisfy requests
@@ -3076,11 +2894,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
*/
if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
(s.syncing && (s.uptodate < disks)) || s.expanding)
- handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
+ handle_stripe_fill6(sh, &s, &r6s, disks);
/* now to consider writing and what else, if anything should be read */
if (s.to_write)
- handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
+ handle_stripe_dirtying6(conf, sh, &s, &r6s, disks);
/* maybe we need to check and possibly fix the parity for this stripe
* Any reads will already have been scheduled, so we just see if enough
@@ -3136,7 +2954,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
}
if (s.expanding && s.locked == 0 &&
- !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+ !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
handle_stripe_expansion(conf, sh, &r6s);
unlock:
@@ -3146,68 +2964,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
if (unlikely(blocked_rdev))
md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
- return_io(return_bi);
-
- for (i=disks; i-- ;) {
- int rw;
- struct bio *bi;
- mdk_rdev_t *rdev;
- if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = WRITE;
- else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = READ;
- else
- continue;
-
- set_bit(STRIPE_IO_STARTED, &sh->state);
-
- bi = &sh->dev[i].req;
-
- bi->bi_rw = rw;
- if (rw == WRITE)
- bi->bi_end_io = raid5_end_write_request;
- else
- bi->bi_end_io = raid5_end_read_request;
-
- rcu_read_lock();
- rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && test_bit(Faulty, &rdev->flags))
- rdev = NULL;
- if (rdev)
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
+ ops_run_io(sh, &s);
- if (rdev) {
- if (s.syncing || s.expanding || s.expanded)
- md_sync_acct(rdev->bdev, STRIPE_SECTORS);
-
- bi->bi_bdev = rdev->bdev;
- pr_debug("for %llu schedule op %ld on disc %d\n",
- (unsigned long long)sh->sector, bi->bi_rw, i);
- atomic_inc(&sh->count);
- bi->bi_sector = sh->sector + rdev->data_offset;
- bi->bi_flags = 1 << BIO_UPTODATE;
- bi->bi_vcnt = 1;
- bi->bi_max_vecs = 1;
- bi->bi_idx = 0;
- bi->bi_io_vec = &sh->dev[i].vec;
- bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
- bi->bi_io_vec[0].bv_offset = 0;
- bi->bi_size = STRIPE_SIZE;
- bi->bi_next = NULL;
- if (rw == WRITE &&
- test_bit(R5_ReWrite, &sh->dev[i].flags))
- atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
- generic_make_request(bi);
- } else {
- if (rw == WRITE)
- set_bit(STRIPE_DEGRADED, &sh->state);
- pr_debug("skip op %ld on disc %d for sector %llu\n",
- bi->bi_rw, i, (unsigned long long)sh->sector);
- clear_bit(R5_LOCKED, &sh->dev[i].flags);
- set_bit(STRIPE_HANDLE, &sh->state);
- }
- }
+ return_io(return_bi);
}
static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
@@ -3697,9 +3456,7 @@ static int make_request(struct request_queue *q, struct bio * bi)
if ( rw == WRITE )
md_write_end(mddev);
- bi->bi_end_io(bi,
- test_bit(BIO_UPTODATE, &bi->bi_flags)
- ? 0 : -EIO);
+ bio_endio(bi, 0);
}
return 0;
}
@@ -3785,7 +3542,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
j == raid6_next_disk(sh->pd_idx, sh->disks))
continue;
s = compute_blocknr(sh, j);
- if (s < (mddev->array_size<<1)) {
+ if (s < mddev->array_sectors) {
skipped = 1;
continue;
}
@@ -4002,12 +3759,8 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
spin_lock_irq(&conf->device_lock);
remaining = --raid_bio->bi_phys_segments;
spin_unlock_irq(&conf->device_lock);
- if (remaining == 0) {
-
- raid_bio->bi_end_io(raid_bio,
- test_bit(BIO_UPTODATE, &raid_bio->bi_flags)
- ? 0 : -EIO);
- }
+ if (remaining == 0)
+ bio_endio(raid_bio, 0);
if (atomic_dec_and_test(&conf->active_aligned_reads))
wake_up(&conf->wait_for_stripe);
return handled;
@@ -4094,6 +3847,8 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
unsigned long new;
+ int err;
+
if (len >= PAGE_SIZE)
return -EINVAL;
if (!conf)
@@ -4109,7 +3864,9 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
else
break;
}
- md_allow_write(mddev);
+ err = md_allow_write(mddev);
+ if (err)
+ return err;
while (new > conf->max_nr_stripes) {
if (grow_one_stripe(conf))
conf->max_nr_stripes++;
@@ -4434,7 +4191,7 @@ static int run(mddev_t *mddev)
mddev->queue->backing_dev_info.congested_data = mddev;
mddev->queue->backing_dev_info.congested_fn = raid5_congested;
- mddev->array_size = mddev->size * (conf->previous_raid_disks -
+ mddev->array_sectors = 2 * mddev->size * (conf->previous_raid_disks -
conf->max_degraded);
blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
@@ -4609,35 +4366,41 @@ abort:
static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
raid5_conf_t *conf = mddev->private;
- int found = 0;
+ int err = -EEXIST;
int disk;
struct disk_info *p;
+ int first = 0;
+ int last = conf->raid_disks - 1;
if (mddev->degraded > conf->max_degraded)
/* no point adding a device */
- return 0;
+ return -EINVAL;
+
+ if (rdev->raid_disk >= 0)
+ first = last = rdev->raid_disk;
/*
* find the disk ... but prefer rdev->saved_raid_disk
* if possible.
*/
if (rdev->saved_raid_disk >= 0 &&
+ rdev->saved_raid_disk >= first &&
conf->disks[rdev->saved_raid_disk].rdev == NULL)
disk = rdev->saved_raid_disk;
else
- disk = 0;
- for ( ; disk < conf->raid_disks; disk++)
+ disk = first;
+ for ( ; disk <= last ; disk++)
if ((p=conf->disks + disk)->rdev == NULL) {
clear_bit(In_sync, &rdev->flags);
rdev->raid_disk = disk;
- found = 1;
+ err = 0;
if (rdev->saved_raid_disk != disk)
conf->fullsync = 1;
rcu_assign_pointer(p->rdev, rdev);
break;
}
print_raid5_conf(conf);
- return found;
+ return err;
}
static int raid5_resize(mddev_t *mddev, sector_t sectors)
@@ -4652,8 +4415,9 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
raid5_conf_t *conf = mddev_to_conf(mddev);
sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
- mddev->array_size = (sectors * (mddev->raid_disks-conf->max_degraded))>>1;
- set_capacity(mddev->gendisk, mddev->array_size << 1);
+ mddev->array_sectors = sectors * (mddev->raid_disks
+ - conf->max_degraded);
+ set_capacity(mddev->gendisk, mddev->array_sectors);
mddev->changed = 1;
if (sectors/2 > mddev->size && mddev->recovery_cp == MaxSector) {
mddev->recovery_cp = mddev->size << 1;
@@ -4738,7 +4502,7 @@ static int raid5_start_reshape(mddev_t *mddev)
rdev_for_each(rdev, rtmp, mddev)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
- if (raid5_add_disk(mddev, rdev)) {
+ if (raid5_add_disk(mddev, rdev) == 0) {
char nm[20];
set_bit(In_sync, &rdev->flags);
added_devices++;
@@ -4786,15 +4550,16 @@ static void end_reshape(raid5_conf_t *conf)
struct block_device *bdev;
if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
- conf->mddev->array_size = conf->mddev->size *
+ conf->mddev->array_sectors = 2 * conf->mddev->size *
(conf->raid_disks - conf->max_degraded);
- set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
+ set_capacity(conf->mddev->gendisk, conf->mddev->array_sectors);
conf->mddev->changed = 1;
bdev = bdget_disk(conf->mddev->gendisk, 0);
if (bdev) {
mutex_lock(&bdev->bd_inode->i_mutex);
- i_size_write(bdev->bd_inode, (loff_t)conf->mddev->array_size << 10);
+ i_size_write(bdev->bd_inode,
+ (loff_t)conf->mddev->array_sectors << 9);
mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e208a60c048..e7132770a3b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -233,9 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- clsdev = device_create(dvb_class, adap->device,
+ clsdev = device_create_drvdata(dvb_class, adap->device,
MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- "dvb%d.%s%d", adap->num, dnames[type], id);
+ NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
index 6ec4bf81fc7..77b3c338506 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -20,6 +20,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/mm.h>
#include "dvbdev.h"
#include "pvrusb2-debug.h"
#include "pvrusb2-hdw-internal.h"
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index 05a1376405e..b4824782d85 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -22,6 +22,7 @@
#include "pvrusb2-debug.h"
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 7388d0cee3d..5646a6a3293 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/version.h>
+#include <linux/mm.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index 0a88c44ace0..b7b05842cf2 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index a054668eda1..4e3bfbcdf15 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -51,7 +51,7 @@ struct jmb38x_ms_host {
void __iomem *addr;
spinlock_t lock;
int id;
- char host_id[DEVICE_ID_SIZE];
+ char host_id[32];
int irq;
unsigned int block_pos;
unsigned long timeout_jiffies;
@@ -781,7 +781,7 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
spin_lock_init(&host->lock);
host->id = cnt;
- snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
+ snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d",
host->id);
host->irq = jm->pdev->irq;
host->timeout_jiffies = msecs_to_jiffies(1000);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 75e599b85b6..34402c47027 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1670,7 +1670,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
spin_lock_init(&ioc->fault_reset_work_lock);
- snprintf(ioc->reset_work_q_name, KOBJ_NAME_LEN, "mpt_poll_%d", ioc->id);
+ snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
+ "mpt_poll_%d", ioc->id);
ioc->reset_work_q =
create_singlethread_workqueue(ioc->reset_work_q_name);
if (!ioc->reset_work_q) {
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6adab648dbb..dff048cfa10 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -707,12 +707,12 @@ typedef struct _MPT_ADAPTER
u8 fc_link_speed[2];
spinlock_t fc_rescan_work_lock;
struct work_struct fc_rescan_work;
- char fc_rescan_work_q_name[KOBJ_NAME_LEN];
+ char fc_rescan_work_q_name[20];
struct workqueue_struct *fc_rescan_work_q;
struct scsi_cmnd **ScsiLookup;
spinlock_t scsi_lookup_lock;
- char reset_work_q_name[KOBJ_NAME_LEN];
+ char reset_work_q_name[20];
struct workqueue_struct *reset_work_q;
struct delayed_work fault_reset_work;
spinlock_t fault_reset_work_lock;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index fc31ca6829d..b36cae9ec6d 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -1326,8 +1326,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* initialize workqueue */
- snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
- sh->host_no);
+ snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
+ "mptfc_wq_%d", sh->host_no);
ioc->fc_rescan_work_q =
create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
if (!ioc->fc_rescan_work_q)
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 489d7c5c496..8774c670e66 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -243,29 +243,41 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
/* create user entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "user");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "user");
+ if (rc)
+ goto unreg_dev;
+ }
/* create user entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev))
- sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
- "parent");
+ if (tmp && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&i2o_dev->device.kobj,
+ &tmp->device.kobj, "parent");
+ if (rc)
+ goto rmlink1;
+ }
/* create parent entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev))
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
+ && (tmp != i2o_dev)) {
+ rc = sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+ if (rc)
+ goto rmlink2;
+ }
i2o_driver_notify_device_add_all(i2o_dev);
@@ -273,6 +285,24 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
return 0;
+rmlink2:
+ /* If link creating failed halfway, we loop whole list to cleanup.
+ * And we don't care wrong removing of link, because sysfs_remove_link
+ * will take care of it.
+ */
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ }
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+rmlink1:
+ list_for_each_entry(tmp, &c->devices, list)
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+unreg_dev:
+ list_del(&i2o_dev->list);
+ device_unregister(&i2o_dev->device);
err:
kfree(i2o_dev);
return rc;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 260bade0a5e..9f93c29fed3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -5,6 +5,10 @@
menu "Multifunction device drivers"
depends on HAS_IOMEM
+config MFD_CORE
+ tristate
+ default n
+
config MFD_SM501
tristate "Support for Silicon Motion SM501"
---help---
@@ -38,6 +42,13 @@ config HTC_PASIC3
HTC Magician devices, respectively. Actual functionality is
handled by the leds-pasic3 and ds1wm drivers.
+config MFD_TC6393XB
+ bool "Support Toshiba TC6393XB"
+ depends on HAVE_GPIO_LIB
+ select MFD_CORE
+ help
+ Support for Toshiba Mobile IO Controller TC6393XB
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index eef4e26807d..33daa2f45dd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,10 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
+
+obj-$(CONFIG_MFD_CORE) += mfd-core.o
+
obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
new file mode 100644
index 00000000000..d7d88ce053a
--- /dev/null
+++ b/drivers/mfd/mfd-core.c
@@ -0,0 +1,114 @@
+/*
+ * drivers/mfd/mfd-core.c
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007,2008 Dmitry Baryshkov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+
+static int mfd_add_device(struct platform_device *parent,
+ const struct mfd_cell *cell,
+ struct resource *mem_base,
+ int irq_base)
+{
+ struct resource res[cell->num_resources];
+ struct platform_device *pdev;
+ int ret = -ENOMEM;
+ int r;
+
+ pdev = platform_device_alloc(cell->name, parent->id);
+ if (!pdev)
+ goto fail_alloc;
+
+ pdev->dev.parent = &parent->dev;
+
+ ret = platform_device_add_data(pdev,
+ cell, sizeof(struct mfd_cell));
+ if (ret)
+ goto fail_device;
+
+ memzero(res, sizeof(res));
+ for (r = 0; r < cell->num_resources; r++) {
+ res[r].name = cell->resources[r].name;
+ res[r].flags = cell->resources[r].flags;
+
+ /* Find out base to use */
+ if (cell->resources[r].flags & IORESOURCE_MEM) {
+ res[r].parent = mem_base;
+ res[r].start = mem_base->start +
+ cell->resources[r].start;
+ res[r].end = mem_base->start +
+ cell->resources[r].end;
+ } else if (cell->resources[r].flags & IORESOURCE_IRQ) {
+ res[r].start = irq_base +
+ cell->resources[r].start;
+ res[r].end = irq_base +
+ cell->resources[r].end;
+ } else {
+ res[r].parent = cell->resources[r].parent;
+ res[r].start = cell->resources[r].start;
+ res[r].end = cell->resources[r].end;
+ }
+ }
+
+ platform_device_add_resources(pdev, res, cell->num_resources);
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto fail_device;
+
+ return 0;
+
+/* platform_device_del(pdev); */
+fail_device:
+ platform_device_put(pdev);
+fail_alloc:
+ return ret;
+}
+
+int mfd_add_devices(
+ struct platform_device *parent,
+ const struct mfd_cell *cells, int n_devs,
+ struct resource *mem_base,
+ int irq_base)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < n_devs; i++) {
+ ret = mfd_add_device(parent, cells + i, mem_base, irq_base);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ mfd_remove_devices(parent);
+
+ return ret;
+}
+EXPORT_SYMBOL(mfd_add_devices);
+
+static int mfd_remove_devices_fn(struct device *dev, void *unused)
+{
+ platform_device_unregister(
+ container_of(dev, struct platform_device, dev));
+ return 0;
+}
+
+void mfd_remove_devices(struct platform_device *parent)
+{
+ device_for_each_child(&parent->dev, NULL, mfd_remove_devices_fn);
+}
+EXPORT_SYMBOL(mfd_remove_devices);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
new file mode 100644
index 00000000000..2d87501b6fd
--- /dev/null
+++ b/drivers/mfd/tc6393xb.c
@@ -0,0 +1,600 @@
+/*
+ * Toshiba TC6393XB SoC support
+ *
+ * Copyright(c) 2005-2006 Chris Humbert
+ * Copyright(c) 2005 Dirk Opfer
+ * Copyright(c) 2005 Ian Molton <spyro@f2s.com>
+ * Copyright(c) 2007 Dmitry Baryshkov
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ * Based on locomo.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/gpio.h>
+
+#define SCR_REVID 0x08 /* b Revision ID */
+#define SCR_ISR 0x50 /* b Interrupt Status */
+#define SCR_IMR 0x52 /* b Interrupt Mask */
+#define SCR_IRR 0x54 /* b Interrupt Routing */
+#define SCR_GPER 0x60 /* w GP Enable */
+#define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */
+#define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */
+#define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */
+#define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */
+#define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */
+#define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */
+#define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */
+#define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */
+#define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */
+#define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */
+#define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */
+#define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */
+#define SCR_CCR 0x98 /* w Clock Control */
+#define SCR_PLL2CR 0x9a /* w PLL2 Control */
+#define SCR_PLL1CR 0x9c /* l PLL1 Control */
+#define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */
+#define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */
+#define SCR_FER 0xe0 /* b Function Enable */
+#define SCR_MCR 0xe4 /* w Mode Control */
+#define SCR_CONFIG 0xfc /* b Configuration Control */
+#define SCR_DEBUG 0xff /* b Debug */
+
+#define SCR_CCR_CK32K BIT(0)
+#define SCR_CCR_USBCK BIT(1)
+#define SCR_CCR_UNK1 BIT(4)
+#define SCR_CCR_MCLK_MASK (7 << 8)
+#define SCR_CCR_MCLK_OFF (0 << 8)
+#define SCR_CCR_MCLK_12 (1 << 8)
+#define SCR_CCR_MCLK_24 (2 << 8)
+#define SCR_CCR_MCLK_48 (3 << 8)
+#define SCR_CCR_HCLK_MASK (3 << 12)
+#define SCR_CCR_HCLK_24 (0 << 12)
+#define SCR_CCR_HCLK_48 (1 << 12)
+
+#define SCR_FER_USBEN BIT(0) /* USB host enable */
+#define SCR_FER_LCDCVEN BIT(1) /* polysilicon TFT enable */
+#define SCR_FER_SLCDEN BIT(2) /* SLCD enable */
+
+#define SCR_MCR_RDY_MASK (3 << 0)
+#define SCR_MCR_RDY_OPENDRAIN (0 << 0)
+#define SCR_MCR_RDY_TRISTATE (1 << 0)
+#define SCR_MCR_RDY_PUSHPULL (2 << 0)
+#define SCR_MCR_RDY_UNK BIT(2)
+#define SCR_MCR_RDY_EN BIT(3)
+#define SCR_MCR_INT_MASK (3 << 4)
+#define SCR_MCR_INT_OPENDRAIN (0 << 4)
+#define SCR_MCR_INT_TRISTATE (1 << 4)
+#define SCR_MCR_INT_PUSHPULL (2 << 4)
+#define SCR_MCR_INT_UNK BIT(6)
+#define SCR_MCR_INT_EN BIT(7)
+/* bits 8 - 16 are unknown */
+
+#define TC_GPIO_BIT(i) (1 << (i & 0x7))
+
+/*--------------------------------------------------------------------------*/
+
+struct tc6393xb {
+ void __iomem *scr;
+
+ struct gpio_chip gpio;
+
+ struct clk *clk; /* 3,6 Mhz */
+
+ spinlock_t lock; /* protects RMW cycles */
+
+ struct {
+ u8 fer;
+ u16 ccr;
+ u8 gpi_bcr[3];
+ u8 gpo_dsr[3];
+ u8 gpo_doecr[3];
+ } suspend_state;
+
+ struct resource rscr;
+ struct resource *iomem;
+ int irq;
+ int irq_base;
+};
+
+enum {
+ TC6393XB_CELL_NAND,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_nand_enable(struct platform_device *nand)
+{
+ struct platform_device *dev = to_platform_device(nand->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ /* SMD buffer on */
+ dev_dbg(&dev->dev, "SMD buffer on\n");
+ iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static struct resource __devinitdata tc6393xb_nand_resources[] = {
+ {
+ .name = TMIO_NAND_CONFIG,
+ .start = 0x0100,
+ .end = 0x01ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = TMIO_NAND_CONTROL,
+ .start = 0x1000,
+ .end = 0x1007,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = TMIO_NAND_IRQ,
+ .start = IRQ_TC6393_NAND,
+ .end = IRQ_TC6393_NAND,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell __devinitdata tc6393xb_cells[] = {
+ [TC6393XB_CELL_NAND] = {
+ .name = "tmio-nand",
+ .enable = tc6393xb_nand_enable,
+ .num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
+ .resources = tc6393xb_nand_resources,
+ },
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_gpio_get(struct gpio_chip *chip,
+ unsigned offset)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+
+ /* XXX: does dsr also represent inputs? */
+ return ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
+ & TC_GPIO_BIT(offset);
+}
+
+static void __tc6393xb_gpio_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ u8 dsr;
+
+ dsr = ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+ if (value)
+ dsr |= TC_GPIO_BIT(offset);
+ else
+ dsr &= ~TC_GPIO_BIT(offset);
+
+ iowrite8(dsr, tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+}
+
+static void tc6393xb_gpio_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ __tc6393xb_gpio_set(chip, offset, value);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
+ unsigned offset)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+ u8 doecr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+ doecr &= ~TC_GPIO_BIT(offset);
+ iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+ unsigned long flags;
+ u8 doecr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ __tc6393xb_gpio_set(chip, offset, value);
+
+ doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+ doecr |= TC_GPIO_BIT(offset);
+ iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
+{
+ tc6393xb->gpio.label = "tc6393xb";
+ tc6393xb->gpio.base = gpio_base;
+ tc6393xb->gpio.ngpio = 16;
+ tc6393xb->gpio.set = tc6393xb_gpio_set;
+ tc6393xb->gpio.get = tc6393xb_gpio_get;
+ tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
+ tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
+
+ return gpiochip_add(&tc6393xb->gpio);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void
+tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct tc6393xb *tc6393xb = get_irq_data(irq);
+ unsigned int isr;
+ unsigned int i, irq_base;
+
+ irq_base = tc6393xb->irq_base;
+
+ while ((isr = ioread8(tc6393xb->scr + SCR_ISR) &
+ ~ioread8(tc6393xb->scr + SCR_IMR)))
+ for (i = 0; i < TC6393XB_NR_IRQS; i++) {
+ if (isr & (1 << i))
+ generic_handle_irq(irq_base + i);
+ }
+}
+
+static void tc6393xb_irq_ack(unsigned int irq)
+{
+}
+
+static void tc6393xb_irq_mask(unsigned int irq)
+{
+ struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+ unsigned long flags;
+ u8 imr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+ imr = ioread8(tc6393xb->scr + SCR_IMR);
+ imr |= 1 << (irq - tc6393xb->irq_base);
+ iowrite8(imr, tc6393xb->scr + SCR_IMR);
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static void tc6393xb_irq_unmask(unsigned int irq)
+{
+ struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+ unsigned long flags;
+ u8 imr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+ imr = ioread8(tc6393xb->scr + SCR_IMR);
+ imr &= ~(1 << (irq - tc6393xb->irq_base));
+ iowrite8(imr, tc6393xb->scr + SCR_IMR);
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static struct irq_chip tc6393xb_chip = {
+ .name = "tc6393xb",
+ .ack = tc6393xb_irq_ack,
+ .mask = tc6393xb_irq_mask,
+ .unmask = tc6393xb_irq_unmask,
+};
+
+static void tc6393xb_attach_irq(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned int irq, irq_base;
+
+ irq_base = tc6393xb->irq_base;
+
+ for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+ set_irq_chip(irq, &tc6393xb_chip);
+ set_irq_chip_data(irq, tc6393xb);
+ set_irq_handler(irq, handle_edge_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+
+ set_irq_type(tc6393xb->irq, IRQT_FALLING);
+ set_irq_data(tc6393xb->irq, tc6393xb);
+ set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
+}
+
+static void tc6393xb_detach_irq(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned int irq, irq_base;
+
+ set_irq_chained_handler(tc6393xb->irq, NULL);
+ set_irq_data(tc6393xb->irq, NULL);
+
+ irq_base = tc6393xb->irq_base;
+
+ for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+ set_irq_flags(irq, 0);
+ set_irq_chip(irq, NULL);
+ set_irq_chip_data(irq, NULL);
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_hw_init(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int i;
+
+ iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
+ iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
+ iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
+ iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
+ SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
+ BIT(15), tc6393xb->scr + SCR_MCR);
+ iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
+ iowrite8(0, tc6393xb->scr + SCR_IRR);
+ iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
+
+ for (i = 0; i < 3; i++) {
+ iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
+ tc6393xb->scr + SCR_GPO_DSR(i));
+ iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
+ tc6393xb->scr + SCR_GPO_DOECR(i));
+ iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
+ tc6393xb->scr + SCR_GPI_BCR(i));
+ }
+
+ return 0;
+}
+
+static int __devinit tc6393xb_probe(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb;
+ struct resource *iomem;
+ struct resource *rscr;
+ int retval, temp;
+ int i;
+
+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!iomem)
+ return -EINVAL;
+
+ tc6393xb = kzalloc(sizeof *tc6393xb, GFP_KERNEL);
+ if (!tc6393xb) {
+ retval = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ spin_lock_init(&tc6393xb->lock);
+
+ platform_set_drvdata(dev, tc6393xb);
+ tc6393xb->iomem = iomem;
+ tc6393xb->irq = platform_get_irq(dev, 0);
+ tc6393xb->irq_base = tcpd->irq_base;
+
+ tc6393xb->clk = clk_get(&dev->dev, "GPIO27_CLK" /* "CK3P6MI" */);
+ if (IS_ERR(tc6393xb->clk)) {
+ retval = PTR_ERR(tc6393xb->clk);
+ goto err_clk_get;
+ }
+
+ rscr = &tc6393xb->rscr;
+ rscr->name = "tc6393xb-core";
+ rscr->start = iomem->start;
+ rscr->end = iomem->start + 0xff;
+ rscr->flags = IORESOURCE_MEM;
+
+ retval = request_resource(iomem, rscr);
+ if (retval)
+ goto err_request_scr;
+
+ tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+ if (!tc6393xb->scr) {
+ retval = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ retval = clk_enable(tc6393xb->clk);
+ if (retval)
+ goto err_clk_enable;
+
+ retval = tcpd->enable(dev);
+ if (retval)
+ goto err_enable;
+
+ tc6393xb->suspend_state.fer = 0;
+ for (i = 0; i < 3; i++) {
+ tc6393xb->suspend_state.gpo_dsr[i] =
+ (tcpd->scr_gpo_dsr >> (8 * i)) & 0xff;
+ tc6393xb->suspend_state.gpo_doecr[i] =
+ (tcpd->scr_gpo_doecr >> (8 * i)) & 0xff;
+ }
+ /*
+ * It may be necessary to change this back to
+ * platform-dependant code
+ */
+ tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
+ SCR_CCR_HCLK_48;
+
+ retval = tc6393xb_hw_init(dev);
+ if (retval)
+ goto err_hw_init;
+
+ printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
+ ioread8(tc6393xb->scr + SCR_REVID),
+ (unsigned long) iomem->start, tc6393xb->irq);
+
+ tc6393xb->gpio.base = -1;
+
+ if (tcpd->gpio_base >= 0) {
+ retval = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
+ if (retval)
+ goto err_gpio_add;
+ }
+
+ if (tc6393xb->irq)
+ tc6393xb_attach_irq(dev);
+
+ tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
+
+ retval = mfd_add_devices(dev,
+ tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
+ iomem, tcpd->irq_base);
+
+ return 0;
+
+ if (tc6393xb->irq)
+ tc6393xb_detach_irq(dev);
+
+err_gpio_add:
+ if (tc6393xb->gpio.base != -1)
+ temp = gpiochip_remove(&tc6393xb->gpio);
+err_hw_init:
+ tcpd->disable(dev);
+err_clk_enable:
+ clk_disable(tc6393xb->clk);
+err_enable:
+ iounmap(tc6393xb->scr);
+err_ioremap:
+ release_resource(&tc6393xb->rscr);
+err_request_scr:
+ clk_put(tc6393xb->clk);
+err_clk_get:
+ kfree(tc6393xb);
+err_kzalloc:
+ return retval;
+}
+
+static int __devexit tc6393xb_remove(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int ret;
+
+ mfd_remove_devices(dev);
+
+ if (tc6393xb->irq)
+ tc6393xb_detach_irq(dev);
+
+ if (tc6393xb->gpio.base != -1) {
+ ret = gpiochip_remove(&tc6393xb->gpio);
+ if (ret) {
+ dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = tcpd->disable(dev);
+
+ clk_disable(tc6393xb->clk);
+
+ iounmap(tc6393xb->scr);
+
+ release_resource(&tc6393xb->rscr);
+
+ platform_set_drvdata(dev, NULL);
+
+ clk_put(tc6393xb->clk);
+
+ kfree(tc6393xb);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ int i;
+
+
+ tc6393xb->suspend_state.ccr = ioread16(tc6393xb->scr + SCR_CCR);
+ tc6393xb->suspend_state.fer = ioread8(tc6393xb->scr + SCR_FER);
+
+ for (i = 0; i < 3; i++) {
+ tc6393xb->suspend_state.gpo_dsr[i] =
+ ioread8(tc6393xb->scr + SCR_GPO_DSR(i));
+ tc6393xb->suspend_state.gpo_doecr[i] =
+ ioread8(tc6393xb->scr + SCR_GPO_DOECR(i));
+ tc6393xb->suspend_state.gpi_bcr[i] =
+ ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
+ }
+
+ return tcpd->suspend(dev);
+}
+
+static int tc6393xb_resume(struct platform_device *dev)
+{
+ struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+ int ret = tcpd->resume(dev);
+
+ if (ret)
+ return ret;
+
+ return tc6393xb_hw_init(dev);
+}
+#else
+#define tc6393xb_suspend NULL
+#define tc6393xb_resume NULL
+#endif
+
+static struct platform_driver tc6393xb_driver = {
+ .probe = tc6393xb_probe,
+ .remove = __devexit_p(tc6393xb_remove),
+ .suspend = tc6393xb_suspend,
+ .resume = tc6393xb_resume,
+
+ .driver = {
+ .name = "tc6393xb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init tc6393xb_init(void)
+{
+ return platform_driver_register(&tc6393xb_driver);
+}
+
+static void __exit tc6393xb_exit(void)
+{
+ platform_driver_unregister(&tc6393xb_driver);
+}
+
+subsys_initcall(tc6393xb_init);
+module_exit(tc6393xb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
+MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
+MODULE_ALIAS("platform:tc6393xb");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b27ca91fd15..d5bc288b1b0 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -422,4 +422,17 @@ config SGI_XP
this feature will allow for direct communication between SSIs
based on a network adapter and DMA messaging.
+config HP_ILO
+ tristate "Channel interface driver for HP iLO/iLO2 processor"
+ default n
+ help
+ The channel interface driver allows applications to communicate
+ with iLO/iLO2 management processors present on HP ProLiant
+ servers. Upon loading, the driver creates /dev/hpilo/dXccbN files,
+ which can be used to gather data from the management processor,
+ via read and write system calls.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hpilo.
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a6dac6a2e7e..688fe76135e 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
+obj-$(CONFIG_HP_ILO) += hpilo.o
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 5b5a14dab3d..6aa5294dfec 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -211,8 +211,7 @@ int pwm_clk_alloc(unsigned prescale, unsigned div)
if ((mr & 0xffff) == 0) {
mr |= val;
ret = PWM_CPR_CLKA;
- }
- if ((mr & (0xffff << 16)) == 0) {
+ } else if ((mr & (0xffff << 16)) == 0) {
mr |= val << 16;
ret = PWM_CPR_CLKB;
}
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
new file mode 100644
index 00000000000..05e29828923
--- /dev/null
+++ b/drivers/misc/hpilo.c
@@ -0,0 +1,768 @@
+/*
+ * Driver for HP iLO/iLO2 management processor.
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ * David Altobelli <david.altobelli@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/cdev.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include "hpilo.h"
+
+static struct class *ilo_class;
+static unsigned int ilo_major;
+static char ilo_hwdev[MAX_ILO_DEV];
+
+static inline int get_entry_id(int entry)
+{
+ return (entry & ENTRY_MASK_DESCRIPTOR) >> ENTRY_BITPOS_DESCRIPTOR;
+}
+
+static inline int get_entry_len(int entry)
+{
+ return ((entry & ENTRY_MASK_QWORDS) >> ENTRY_BITPOS_QWORDS) << 3;
+}
+
+static inline int mk_entry(int id, int len)
+{
+ int qlen = len & 7 ? (len >> 3) + 1 : len >> 3;
+ return id << ENTRY_BITPOS_DESCRIPTOR | qlen << ENTRY_BITPOS_QWORDS;
+}
+
+static inline int desc_mem_sz(int nr_entry)
+{
+ return nr_entry << L2_QENTRY_SZ;
+}
+
+/*
+ * FIFO queues, shared with hardware.
+ *
+ * If a queue has empty slots, an entry is added to the queue tail,
+ * and that entry is marked as occupied.
+ * Entries can be dequeued from the head of the list, when the device
+ * has marked the entry as consumed.
+ *
+ * Returns true on successful queue/dequeue, false on failure.
+ */
+static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
+{
+ struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+ int ret = 0;
+
+ spin_lock(&hw->fifo_lock);
+ if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask]
+ & ENTRY_MASK_O)) {
+ fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |=
+ (entry & ENTRY_MASK_NOSTATE) | fifo_q->merge;
+ fifo_q->tail += 1;
+ ret = 1;
+ }
+ spin_unlock(&hw->fifo_lock);
+
+ return ret;
+}
+
+static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
+{
+ struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+ int ret = 0;
+ u64 c;
+
+ spin_lock(&hw->fifo_lock);
+ c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
+ if (c & ENTRY_MASK_C) {
+ if (entry)
+ *entry = c & ENTRY_MASK_NOSTATE;
+
+ fifo_q->fifobar[fifo_q->head & fifo_q->imask] =
+ (c | ENTRY_MASK) + 1;
+ fifo_q->head += 1;
+ ret = 1;
+ }
+ spin_unlock(&hw->fifo_lock);
+
+ return ret;
+}
+
+static int ilo_pkt_enqueue(struct ilo_hwinfo *hw, struct ccb *ccb,
+ int dir, int id, int len)
+{
+ char *fifobar;
+ int entry;
+
+ if (dir == SENDQ)
+ fifobar = ccb->ccb_u1.send_fifobar;
+ else
+ fifobar = ccb->ccb_u3.recv_fifobar;
+
+ entry = mk_entry(id, len);
+ return fifo_enqueue(hw, fifobar, entry);
+}
+
+static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb,
+ int dir, int *id, int *len, void **pkt)
+{
+ char *fifobar, *desc;
+ int entry = 0, pkt_id = 0;
+ int ret;
+
+ if (dir == SENDQ) {
+ fifobar = ccb->ccb_u1.send_fifobar;
+ desc = ccb->ccb_u2.send_desc;
+ } else {
+ fifobar = ccb->ccb_u3.recv_fifobar;
+ desc = ccb->ccb_u4.recv_desc;
+ }
+
+ ret = fifo_dequeue(hw, fifobar, &entry);
+ if (ret) {
+ pkt_id = get_entry_id(entry);
+ if (id)
+ *id = pkt_id;
+ if (len)
+ *len = get_entry_len(entry);
+ if (pkt)
+ *pkt = (void *)(desc + desc_mem_sz(pkt_id));
+ }
+
+ return ret;
+}
+
+static inline void doorbell_set(struct ccb *ccb)
+{
+ iowrite8(1, ccb->ccb_u5.db_base);
+}
+
+static inline void doorbell_clr(struct ccb *ccb)
+{
+ iowrite8(2, ccb->ccb_u5.db_base);
+}
+static inline int ctrl_set(int l2sz, int idxmask, int desclim)
+{
+ int active = 0, go = 1;
+ return l2sz << CTRL_BITPOS_L2SZ |
+ idxmask << CTRL_BITPOS_FIFOINDEXMASK |
+ desclim << CTRL_BITPOS_DESCLIMIT |
+ active << CTRL_BITPOS_A |
+ go << CTRL_BITPOS_G;
+}
+static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
+{
+ /* for simplicity, use the same parameters for send and recv ctrls */
+ ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+ ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+}
+
+static inline int fifo_sz(int nr_entry)
+{
+ /* size of a fifo is determined by the number of entries it contains */
+ return (nr_entry * sizeof(u64)) + FIFOHANDLESIZE;
+}
+
+static void fifo_setup(void *base_addr, int nr_entry)
+{
+ struct fifo *fifo_q = base_addr;
+ int i;
+
+ /* set up an empty fifo */
+ fifo_q->head = 0;
+ fifo_q->tail = 0;
+ fifo_q->reset = 0;
+ fifo_q->nrents = nr_entry;
+ fifo_q->imask = nr_entry - 1;
+ fifo_q->merge = ENTRY_MASK_O;
+
+ for (i = 0; i < nr_entry; i++)
+ fifo_q->fifobar[i] = 0;
+}
+
+static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
+{
+ struct ccb *driver_ccb;
+ struct ccb __iomem *device_ccb;
+ int retries;
+
+ driver_ccb = &data->driver_ccb;
+ device_ccb = data->mapped_ccb;
+
+ /* complicated dance to tell the hw we are stopping */
+ doorbell_clr(driver_ccb);
+ iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G),
+ &device_ccb->send_ctrl);
+ iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G),
+ &device_ccb->recv_ctrl);
+
+ /* give iLO some time to process stop request */
+ for (retries = 1000; retries > 0; retries--) {
+ doorbell_set(driver_ccb);
+ udelay(1);
+ if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
+ &&
+ !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A)))
+ break;
+ }
+ if (retries == 0)
+ dev_err(&pdev->dev, "Closing, but controller still active\n");
+
+ /* clear the hw ccb */
+ memset_io(device_ccb, 0, sizeof(struct ccb));
+
+ /* free resources used to back send/recv queues */
+ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+}
+
+static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
+{
+ char *dma_va, *dma_pa;
+ int pkt_id, pkt_sz, i, error;
+ struct ccb *driver_ccb, *ilo_ccb;
+ struct pci_dev *pdev;
+
+ driver_ccb = &data->driver_ccb;
+ ilo_ccb = &data->ilo_ccb;
+ pdev = hw->ilo_dev;
+
+ data->dma_size = 2 * fifo_sz(NR_QENTRY) +
+ 2 * desc_mem_sz(NR_QENTRY) +
+ ILO_START_ALIGN + ILO_CACHE_SZ;
+
+ error = -ENOMEM;
+ data->dma_va = pci_alloc_consistent(pdev, data->dma_size,
+ &data->dma_pa);
+ if (!data->dma_va)
+ goto out;
+
+ dma_va = (char *)data->dma_va;
+ dma_pa = (char *)data->dma_pa;
+
+ memset(dma_va, 0, data->dma_size);
+
+ dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN);
+ dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_START_ALIGN);
+
+ /*
+ * Create two ccb's, one with virt addrs, one with phys addrs.
+ * Copy the phys addr ccb to device shared mem.
+ */
+ ctrl_setup(driver_ccb, NR_QENTRY, L2_QENTRY_SZ);
+ ctrl_setup(ilo_ccb, NR_QENTRY, L2_QENTRY_SZ);
+
+ fifo_setup(dma_va, NR_QENTRY);
+ driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE;
+ ilo_ccb->ccb_u1.send_fifobar = dma_pa + FIFOHANDLESIZE;
+ dma_va += fifo_sz(NR_QENTRY);
+ dma_pa += fifo_sz(NR_QENTRY);
+
+ dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ);
+ dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_CACHE_SZ);
+
+ fifo_setup(dma_va, NR_QENTRY);
+ driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE;
+ ilo_ccb->ccb_u3.recv_fifobar = dma_pa + FIFOHANDLESIZE;
+ dma_va += fifo_sz(NR_QENTRY);
+ dma_pa += fifo_sz(NR_QENTRY);
+
+ driver_ccb->ccb_u2.send_desc = dma_va;
+ ilo_ccb->ccb_u2.send_desc = dma_pa;
+ dma_pa += desc_mem_sz(NR_QENTRY);
+ dma_va += desc_mem_sz(NR_QENTRY);
+
+ driver_ccb->ccb_u4.recv_desc = dma_va;
+ ilo_ccb->ccb_u4.recv_desc = dma_pa;
+
+ driver_ccb->channel = slot;
+ ilo_ccb->channel = slot;
+
+ driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE);
+ ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */
+
+ /* copy the ccb with physical addrs to device memory */
+ data->mapped_ccb = (struct ccb __iomem *)
+ (hw->ram_vaddr + (slot * ILOHW_CCB_SZ));
+ memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb));
+
+ /* put packets on the send and receive queues */
+ pkt_sz = 0;
+ for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) {
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz);
+ doorbell_set(driver_ccb);
+ }
+
+ pkt_sz = desc_mem_sz(1);
+ for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++)
+ ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz);
+
+ doorbell_clr(driver_ccb);
+
+ /* make sure iLO is really handling requests */
+ for (i = 1000; i > 0; i--) {
+ if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
+ break;
+ udelay(1);
+ }
+
+ if (i) {
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0);
+ doorbell_set(driver_ccb);
+ } else {
+ dev_err(&pdev->dev, "Open could not dequeue a packet\n");
+ error = -EBUSY;
+ goto free;
+ }
+
+ return 0;
+free:
+ pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+out:
+ return error;
+}
+
+static inline int is_channel_reset(struct ccb *ccb)
+{
+ /* check for this particular channel needing a reset */
+ return FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset;
+}
+
+static inline void set_channel_reset(struct ccb *ccb)
+{
+ /* set a flag indicating this channel needs a reset */
+ FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1;
+}
+
+static inline int is_device_reset(struct ilo_hwinfo *hw)
+{
+ /* check for global reset condition */
+ return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET);
+}
+
+static inline void clear_device(struct ilo_hwinfo *hw)
+{
+ /* clear the device (reset bits, pending channel entries) */
+ iowrite32(-1, &hw->mmio_vaddr[DB_OUT]);
+}
+
+static void ilo_locked_reset(struct ilo_hwinfo *hw)
+{
+ int slot;
+
+ /*
+ * Mapped memory is zeroed on ilo reset, so set a per ccb flag
+ * to indicate that this ccb needs to be closed and reopened.
+ */
+ for (slot = 0; slot < MAX_CCB; slot++) {
+ if (!hw->ccb_alloc[slot])
+ continue;
+ set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
+ }
+
+ clear_device(hw);
+}
+
+static void ilo_reset(struct ilo_hwinfo *hw)
+{
+ spin_lock(&hw->alloc_lock);
+
+ /* reset might have been handled after lock was taken */
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ spin_unlock(&hw->alloc_lock);
+}
+
+static ssize_t ilo_read(struct file *fp, char __user *buf,
+ size_t len, loff_t *off)
+{
+ int err, found, cnt, pkt_id, pkt_len;
+ struct ccb_data *data;
+ struct ccb *driver_ccb;
+ struct ilo_hwinfo *hw;
+ void *pkt;
+
+ data = fp->private_data;
+ driver_ccb = &data->driver_ccb;
+ hw = data->ilo_hw;
+
+ if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+ /*
+ * If the device has been reset, applications
+ * need to close and reopen all ccbs.
+ */
+ ilo_reset(hw);
+ return -ENODEV;
+ }
+
+ /*
+ * This function is to be called when data is expected
+ * in the channel, and will return an error if no packet is found
+ * during the loop below. The sleep/retry logic is to allow
+ * applications to call read() immediately post write(),
+ * and give iLO some time to process the sent packet.
+ */
+ cnt = 20;
+ do {
+ /* look for a received packet */
+ found = ilo_pkt_dequeue(hw, driver_ccb, RECVQ, &pkt_id,
+ &pkt_len, &pkt);
+ if (found)
+ break;
+ cnt--;
+ msleep(100);
+ } while (!found && cnt);
+
+ if (!found)
+ return -EAGAIN;
+
+ /* only copy the length of the received packet */
+ if (pkt_len < len)
+ len = pkt_len;
+
+ err = copy_to_user(buf, pkt, len);
+
+ /* return the received packet to the queue */
+ ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, desc_mem_sz(1));
+
+ return err ? -EFAULT : len;
+}
+
+static ssize_t ilo_write(struct file *fp, const char __user *buf,
+ size_t len, loff_t *off)
+{
+ int err, pkt_id, pkt_len;
+ struct ccb_data *data;
+ struct ccb *driver_ccb;
+ struct ilo_hwinfo *hw;
+ void *pkt;
+
+ data = fp->private_data;
+ driver_ccb = &data->driver_ccb;
+ hw = data->ilo_hw;
+
+ if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+ /*
+ * If the device has been reset, applications
+ * need to close and reopen all ccbs.
+ */
+ ilo_reset(hw);
+ return -ENODEV;
+ }
+
+ /* get a packet to send the user command */
+ if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt))
+ return -EBUSY;
+
+ /* limit the length to the length of the packet */
+ if (pkt_len < len)
+ len = pkt_len;
+
+ /* on failure, set the len to 0 to return empty packet to the device */
+ err = copy_from_user(pkt, buf, len);
+ if (err)
+ len = 0;
+
+ /* send the packet */
+ ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len);
+ doorbell_set(driver_ccb);
+
+ return err ? -EFAULT : len;
+}
+
+static int ilo_close(struct inode *ip, struct file *fp)
+{
+ int slot;
+ struct ccb_data *data;
+ struct ilo_hwinfo *hw;
+
+ slot = iminor(ip) % MAX_CCB;
+ hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+ spin_lock(&hw->alloc_lock);
+
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ if (hw->ccb_alloc[slot]->ccb_cnt == 1) {
+
+ data = fp->private_data;
+
+ ilo_ccb_close(hw->ilo_dev, data);
+
+ kfree(data);
+ hw->ccb_alloc[slot] = NULL;
+ } else
+ hw->ccb_alloc[slot]->ccb_cnt--;
+
+ spin_unlock(&hw->alloc_lock);
+
+ return 0;
+}
+
+static int ilo_open(struct inode *ip, struct file *fp)
+{
+ int slot, error;
+ struct ccb_data *data;
+ struct ilo_hwinfo *hw;
+
+ slot = iminor(ip) % MAX_CCB;
+ hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+ /* new ccb allocation */
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ spin_lock(&hw->alloc_lock);
+
+ if (is_device_reset(hw))
+ ilo_locked_reset(hw);
+
+ /* each fd private_data holds sw/hw view of ccb */
+ if (hw->ccb_alloc[slot] == NULL) {
+ /* create a channel control block for this minor */
+ error = ilo_ccb_open(hw, data, slot);
+ if (!error) {
+ hw->ccb_alloc[slot] = data;
+ hw->ccb_alloc[slot]->ccb_cnt = 1;
+ hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL;
+ hw->ccb_alloc[slot]->ilo_hw = hw;
+ } else
+ kfree(data);
+ } else {
+ kfree(data);
+ if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) {
+ /*
+ * The channel exists, and either this open
+ * or a previous open of this channel wants
+ * exclusive access.
+ */
+ error = -EBUSY;
+ } else {
+ hw->ccb_alloc[slot]->ccb_cnt++;
+ error = 0;
+ }
+ }
+ spin_unlock(&hw->alloc_lock);
+
+ if (!error)
+ fp->private_data = hw->ccb_alloc[slot];
+
+ return error;
+}
+
+static const struct file_operations ilo_fops = {
+ .owner = THIS_MODULE,
+ .read = ilo_read,
+ .write = ilo_write,
+ .open = ilo_open,
+ .release = ilo_close,
+};
+
+static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+ pci_iounmap(pdev, hw->db_vaddr);
+ pci_iounmap(pdev, hw->ram_vaddr);
+ pci_iounmap(pdev, hw->mmio_vaddr);
+}
+
+static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+ int error = -ENOMEM;
+
+ /* map the memory mapped i/o registers */
+ hw->mmio_vaddr = pci_iomap(pdev, 1, 0);
+ if (hw->mmio_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping mmio\n");
+ goto out;
+ }
+
+ /* map the adapter shared memory region */
+ hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ);
+ if (hw->ram_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping shared mem\n");
+ goto mmio_free;
+ }
+
+ /* map the doorbell aperture */
+ hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE);
+ if (hw->db_vaddr == NULL) {
+ dev_err(&pdev->dev, "Error mapping doorbell\n");
+ goto ram_free;
+ }
+
+ return 0;
+ram_free:
+ pci_iounmap(pdev, hw->ram_vaddr);
+mmio_free:
+ pci_iounmap(pdev, hw->mmio_vaddr);
+out:
+ return error;
+}
+
+static void ilo_remove(struct pci_dev *pdev)
+{
+ int i, minor;
+ struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
+
+ clear_device(ilo_hw);
+
+ minor = MINOR(ilo_hw->cdev.dev);
+ for (i = minor; i < minor + MAX_CCB; i++)
+ device_destroy(ilo_class, MKDEV(ilo_major, i));
+
+ cdev_del(&ilo_hw->cdev);
+ ilo_unmap_device(pdev, ilo_hw);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ kfree(ilo_hw);
+ ilo_hwdev[(minor / MAX_CCB)] = 0;
+}
+
+static int __devinit ilo_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int devnum, minor, start, error;
+ struct ilo_hwinfo *ilo_hw;
+
+ /* find a free range for device files */
+ for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) {
+ if (ilo_hwdev[devnum] == 0) {
+ ilo_hwdev[devnum] = 1;
+ break;
+ }
+ }
+
+ if (devnum == MAX_ILO_DEV) {
+ dev_err(&pdev->dev, "Error finding free device\n");
+ return -ENODEV;
+ }
+
+ /* track global allocations for this device */
+ error = -ENOMEM;
+ ilo_hw = kzalloc(sizeof(*ilo_hw), GFP_KERNEL);
+ if (!ilo_hw)
+ goto out;
+
+ ilo_hw->ilo_dev = pdev;
+ spin_lock_init(&ilo_hw->alloc_lock);
+ spin_lock_init(&ilo_hw->fifo_lock);
+
+ error = pci_enable_device(pdev);
+ if (error)
+ goto free;
+
+ pci_set_master(pdev);
+
+ error = pci_request_regions(pdev, ILO_NAME);
+ if (error)
+ goto disable;
+
+ error = ilo_map_device(pdev, ilo_hw);
+ if (error)
+ goto free_regions;
+
+ pci_set_drvdata(pdev, ilo_hw);
+ clear_device(ilo_hw);
+
+ cdev_init(&ilo_hw->cdev, &ilo_fops);
+ ilo_hw->cdev.owner = THIS_MODULE;
+ start = devnum * MAX_CCB;
+ error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB);
+ if (error) {
+ dev_err(&pdev->dev, "Could not add cdev\n");
+ goto unmap;
+ }
+
+ for (minor = 0 ; minor < MAX_CCB; minor++) {
+ struct device *dev;
+ dev = device_create(ilo_class, &pdev->dev,
+ MKDEV(ilo_major, minor), NULL,
+ "hpilo!d%dccb%d", devnum, minor);
+ if (IS_ERR(dev))
+ dev_err(&pdev->dev, "Could not create files\n");
+ }
+
+ return 0;
+unmap:
+ ilo_unmap_device(pdev, ilo_hw);
+free_regions:
+ pci_release_regions(pdev);
+disable:
+ pci_disable_device(pdev);
+free:
+ kfree(ilo_hw);
+out:
+ ilo_hwdev[devnum] = 0;
+ return error;
+}
+
+static struct pci_device_id ilo_devices[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, ilo_devices);
+
+static struct pci_driver ilo_driver = {
+ .name = ILO_NAME,
+ .id_table = ilo_devices,
+ .probe = ilo_probe,
+ .remove = __devexit_p(ilo_remove),
+};
+
+static int __init ilo_init(void)
+{
+ int error;
+ dev_t dev;
+
+ ilo_class = class_create(THIS_MODULE, "iLO");
+ if (IS_ERR(ilo_class)) {
+ error = PTR_ERR(ilo_class);
+ goto out;
+ }
+
+ error = alloc_chrdev_region(&dev, 0, MAX_OPEN, ILO_NAME);
+ if (error)
+ goto class_destroy;
+
+ ilo_major = MAJOR(dev);
+
+ error = pci_register_driver(&ilo_driver);
+ if (error)
+ goto chr_remove;
+
+ return 0;
+chr_remove:
+ unregister_chrdev_region(dev, MAX_OPEN);
+class_destroy:
+ class_destroy(ilo_class);
+out:
+ return error;
+}
+
+static void __exit ilo_exit(void)
+{
+ pci_unregister_driver(&ilo_driver);
+ unregister_chrdev_region(MKDEV(ilo_major, 0), MAX_OPEN);
+ class_destroy(ilo_class);
+}
+
+MODULE_VERSION("0.05");
+MODULE_ALIAS(ILO_NAME);
+MODULE_DESCRIPTION(ILO_NAME);
+MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
+MODULE_LICENSE("GPL v2");
+
+module_init(ilo_init);
+module_exit(ilo_exit);
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h
new file mode 100644
index 00000000000..a281207696c
--- /dev/null
+++ b/drivers/misc/hpilo.h
@@ -0,0 +1,189 @@
+/*
+ * linux/drivers/char/hpilo.h
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ * David Altobelli <david.altobelli@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __HPILO_H
+#define __HPILO_H
+
+#define ILO_NAME "hpilo"
+
+/* max number of open channel control blocks per device, hw limited to 32 */
+#define MAX_CCB 8
+/* max number of supported devices */
+#define MAX_ILO_DEV 1
+/* max number of files */
+#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV)
+
+/*
+ * Per device, used to track global memory allocations.
+ */
+struct ilo_hwinfo {
+ /* mmio registers on device */
+ char __iomem *mmio_vaddr;
+
+ /* doorbell registers on device */
+ char __iomem *db_vaddr;
+
+ /* shared memory on device used for channel control blocks */
+ char __iomem *ram_vaddr;
+
+ /* files corresponding to this device */
+ struct ccb_data *ccb_alloc[MAX_CCB];
+
+ struct pci_dev *ilo_dev;
+
+ spinlock_t alloc_lock;
+ spinlock_t fifo_lock;
+
+ struct cdev cdev;
+};
+
+/* offset from mmio_vaddr */
+#define DB_OUT 0xD4
+/* DB_OUT reset bit */
+#define DB_RESET 26
+
+/*
+ * Channel control block. Used to manage hardware queues.
+ * The format must match hw's version. The hw ccb is 128 bytes,
+ * but the context area shouldn't be touched by the driver.
+ */
+#define ILOSW_CCB_SZ 64
+#define ILOHW_CCB_SZ 128
+struct ccb {
+ union {
+ char *send_fifobar;
+ u64 padding1;
+ } ccb_u1;
+ union {
+ char *send_desc;
+ u64 padding2;
+ } ccb_u2;
+ u64 send_ctrl;
+
+ union {
+ char *recv_fifobar;
+ u64 padding3;
+ } ccb_u3;
+ union {
+ char *recv_desc;
+ u64 padding4;
+ } ccb_u4;
+ u64 recv_ctrl;
+
+ union {
+ char __iomem *db_base;
+ u64 padding5;
+ } ccb_u5;
+
+ u64 channel;
+
+ /* unused context area (64 bytes) */
+};
+
+/* ccb queue parameters */
+#define SENDQ 1
+#define RECVQ 2
+#define NR_QENTRY 4
+#define L2_QENTRY_SZ 12
+
+/* ccb ctrl bitfields */
+#define CTRL_BITPOS_L2SZ 0
+#define CTRL_BITPOS_FIFOINDEXMASK 4
+#define CTRL_BITPOS_DESCLIMIT 18
+#define CTRL_BITPOS_A 30
+#define CTRL_BITPOS_G 31
+
+/* ccb doorbell macros */
+#define L2_DB_SIZE 14
+#define ONE_DB_SIZE (1 << L2_DB_SIZE)
+
+/*
+ * Per fd structure used to track the ccb allocated to that dev file.
+ */
+struct ccb_data {
+ /* software version of ccb, using virtual addrs */
+ struct ccb driver_ccb;
+
+ /* hardware version of ccb, using physical addrs */
+ struct ccb ilo_ccb;
+
+ /* hardware ccb is written to this shared mapped device memory */
+ struct ccb __iomem *mapped_ccb;
+
+ /* dma'able memory used for send/recv queues */
+ void *dma_va;
+ dma_addr_t dma_pa;
+ size_t dma_size;
+
+ /* pointer to hardware device info */
+ struct ilo_hwinfo *ilo_hw;
+
+ /* usage count, to allow for shared ccb's */
+ int ccb_cnt;
+
+ /* open wanted exclusive access to this ccb */
+ int ccb_excl;
+};
+
+/*
+ * FIFO queue structure, shared with hw.
+ */
+#define ILO_START_ALIGN 4096
+#define ILO_CACHE_SZ 128
+struct fifo {
+ u64 nrents; /* user requested number of fifo entries */
+ u64 imask; /* mask to extract valid fifo index */
+ u64 merge; /* O/C bits to merge in during enqueue operation */
+ u64 reset; /* set to non-zero when the target device resets */
+ u8 pad_0[ILO_CACHE_SZ - (sizeof(u64) * 4)];
+
+ u64 head;
+ u8 pad_1[ILO_CACHE_SZ - (sizeof(u64))];
+
+ u64 tail;
+ u8 pad_2[ILO_CACHE_SZ - (sizeof(u64))];
+
+ u64 fifobar[1];
+};
+
+/* convert between struct fifo, and the fifobar, which is saved in the ccb */
+#define FIFOHANDLESIZE (sizeof(struct fifo) - sizeof(u64))
+#define FIFOBARTOHANDLE(_fifo) \
+ ((struct fifo *)(((char *)(_fifo)) - FIFOHANDLESIZE))
+
+/* the number of qwords to consume from the entry descriptor */
+#define ENTRY_BITPOS_QWORDS 0
+/* descriptor index number (within a specified queue) */
+#define ENTRY_BITPOS_DESCRIPTOR 10
+/* state bit, fifo entry consumed by consumer */
+#define ENTRY_BITPOS_C 22
+/* state bit, fifo entry is occupied */
+#define ENTRY_BITPOS_O 23
+
+#define ENTRY_BITS_QWORDS 10
+#define ENTRY_BITS_DESCRIPTOR 12
+#define ENTRY_BITS_C 1
+#define ENTRY_BITS_O 1
+#define ENTRY_BITS_TOTAL \
+ (ENTRY_BITS_C + ENTRY_BITS_O + \
+ ENTRY_BITS_QWORDS + ENTRY_BITS_DESCRIPTOR)
+
+/* extract various entry fields */
+#define ENTRY_MASK ((1 << ENTRY_BITS_TOTAL) - 1)
+#define ENTRY_MASK_C (((1 << ENTRY_BITS_C) - 1) << ENTRY_BITPOS_C)
+#define ENTRY_MASK_O (((1 << ENTRY_BITS_O) - 1) << ENTRY_BITPOS_O)
+#define ENTRY_MASK_QWORDS \
+ (((1 << ENTRY_BITS_QWORDS) - 1) << ENTRY_BITPOS_QWORDS)
+#define ENTRY_MASK_DESCRIPTOR \
+ (((1 << ENTRY_BITS_DESCRIPTOR) - 1) << ENTRY_BITPOS_DESCRIPTOR)
+
+#define ENTRY_MASK_NOSTATE (ENTRY_MASK >> (ENTRY_BITS_C + ENTRY_BITS_O))
+
+#endif /* __HPILO_H */
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 18616247009..4ce3bdc2f95 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -399,8 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
goto err_irq;
}
- if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
- minor), "phantom%u", minor)))
+ if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
+ MKDEV(phantom_major, minor),
+ NULL, "phantom%u", minor)))
dev_err(&pdev->dev, "can't create device\n");
pci_set_drvdata(pdev, pht);
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 08256ed0d9a..579b01ff82d 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -229,10 +229,11 @@ xpc_hb_checker(void *ignore)
int last_IRQ_count = 0;
int new_IRQ_count;
int force_IRQ = 0;
+ cpumask_of_cpu_ptr(cpumask, XPC_HB_CHECK_CPU);
/* this thread was marked active by xpc_hb_init() */
- set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+ set_cpus_allowed_ptr(current, cpumask);
/* set our heartbeating to other partitions into motion */
xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index d6b9b486417..a067fe43630 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -21,13 +21,17 @@
#define RESULT_UNSUP_HOST 2
#define RESULT_UNSUP_CARD 3
-#define BUFFER_SIZE (PAGE_SIZE * 4)
+#define BUFFER_ORDER 2
+#define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER)
struct mmc_test_card {
struct mmc_card *card;
u8 scratch[BUFFER_SIZE];
u8 *buffer;
+#ifdef CONFIG_HIGHMEM
+ struct page *highmem;
+#endif
};
/*******************************************************************/
@@ -384,14 +388,16 @@ static int mmc_test_transfer(struct mmc_test_card *test,
int ret, i;
unsigned long flags;
+ BUG_ON(blocks * blksz > BUFFER_SIZE);
+
if (write) {
for (i = 0;i < blocks * blksz;i++)
test->scratch[i] = i;
} else {
- memset(test->scratch, 0, BUFFER_SIZE);
+ memset(test->scratch, 0, blocks * blksz);
}
local_irq_save(flags);
- sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+ sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
local_irq_restore(flags);
ret = mmc_test_set_blksize(test, blksz);
@@ -438,7 +444,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
}
} else {
local_irq_save(flags);
- sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+ sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
local_irq_restore(flags);
for (i = 0;i < blocks * blksz;i++) {
if (test->scratch[i] != (u8)i)
@@ -799,6 +805,157 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
return 0;
}
+static int mmc_test_bigsg_write(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ memset(test->buffer, 0, BUFFER_SIZE);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_bigsg_read(struct mmc_test_card *test)
+{
+ int ret, i;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ memset(test->buffer, 0xCD, BUFFER_SIZE);
+
+ sg_init_table(&sg, 1);
+ sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+ if (ret)
+ return ret;
+
+ /* mmc_test_transfer() doesn't check for read overflows */
+ for (i = size;i < BUFFER_SIZE;i++) {
+ if (test->buffer[i] != 0xCD)
+ return RESULT_FAIL;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_HIGHMEM
+
+static int mmc_test_write_high(struct mmc_test_card *test)
+{
+ int ret;
+ struct scatterlist sg;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, 512, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_read_high(struct mmc_test_card *test)
+{
+ int ret;
+ struct scatterlist sg;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, 512, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_multi_write_high(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, size, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_test_multi_read_high(struct mmc_test_card *test)
+{
+ int ret;
+ unsigned int size;
+ struct scatterlist sg;
+
+ if (test->card->host->max_blk_count == 1)
+ return RESULT_UNSUP_HOST;
+
+ size = PAGE_SIZE * 2;
+ size = min(size, test->card->host->max_req_size);
+ size = min(size, test->card->host->max_seg_size);
+ size = min(size, test->card->host->max_blk_count * 512);
+
+ if (size < 1024)
+ return RESULT_UNSUP_HOST;
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, test->highmem, size, 0);
+
+ ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+#endif /* CONFIG_HIGHMEM */
+
static const struct mmc_test_case mmc_test_cases[] = {
{
.name = "Basic write (no data verification)",
@@ -913,6 +1070,53 @@ static const struct mmc_test_case mmc_test_cases[] = {
.name = "Correct xfer_size at read (midway failure)",
.run = mmc_test_multi_xfersize_read,
},
+
+ {
+ .name = "Over-sized SG list write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_bigsg_write,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Over-sized SG list read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_bigsg_read,
+ .cleanup = mmc_test_cleanup,
+ },
+
+#ifdef CONFIG_HIGHMEM
+
+ {
+ .name = "Highmem write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_write_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Highmem read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_read_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Multi-block highmem write",
+ .prepare = mmc_test_prepare_write,
+ .run = mmc_test_multi_write_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+ {
+ .name = "Multi-block highmem read",
+ .prepare = mmc_test_prepare_read,
+ .run = mmc_test_multi_read_high,
+ .cleanup = mmc_test_cleanup,
+ },
+
+#endif /* CONFIG_HIGHMEM */
+
};
static struct mutex mmc_test_lock;
@@ -1014,12 +1218,23 @@ static ssize_t mmc_test_store(struct device *dev,
test->card = card;
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+#ifdef CONFIG_HIGHMEM
+ test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+#endif
+
+#ifdef CONFIG_HIGHMEM
+ if (test->buffer && test->highmem) {
+#else
if (test->buffer) {
+#endif
mutex_lock(&mmc_test_lock);
mmc_test_run(test, testcase);
mutex_unlock(&mmc_test_lock);
}
+#ifdef CONFIG_HIGHMEM
+ __free_pages(test->highmem, BUFFER_ORDER);
+#endif
kfree(test->buffer);
kfree(test);
@@ -1041,6 +1256,8 @@ static int mmc_test_probe(struct mmc_card *card)
if (ret)
return ret;
+ dev_info(&card->dev, "Card claimed for testing.\n");
+
return 0;
}
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7731ddefdc1..3dee97e7d16 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -148,7 +148,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
printk(KERN_WARNING "%s: unable to allocate "
"bounce buffer\n", mmc_card_name(card));
} else {
- blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+ blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
blk_queue_max_sectors(mq->queue, bouncesz / 512);
blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
@@ -290,55 +290,15 @@ void mmc_queue_resume(struct mmc_queue *mq)
}
}
-static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
- struct scatterlist *src, unsigned int src_len)
-{
- unsigned int chunk;
- char *dst_buf, *src_buf;
- unsigned int dst_size, src_size;
-
- dst_buf = NULL;
- src_buf = NULL;
- dst_size = 0;
- src_size = 0;
-
- while (src_len) {
- BUG_ON(dst_len == 0);
-
- if (dst_size == 0) {
- dst_buf = sg_virt(dst);
- dst_size = dst->length;
- }
-
- if (src_size == 0) {
- src_buf = sg_virt(src);
- src_size = src->length;
- }
-
- chunk = min(dst_size, src_size);
-
- memcpy(dst_buf, src_buf, chunk);
-
- dst_buf += chunk;
- src_buf += chunk;
- dst_size -= chunk;
- src_size -= chunk;
-
- if (dst_size == 0) {
- dst++;
- dst_len--;
- }
-
- if (src_size == 0) {
- src++;
- src_len--;
- }
- }
-}
-
+/*
+ * Prepare the sg list(s) to be handed of to the host driver
+ */
unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
{
unsigned int sg_len;
+ size_t buflen;
+ struct scatterlist *sg;
+ int i;
if (!mq->bounce_buf)
return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
@@ -349,47 +309,52 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
mq->bounce_sg_len = sg_len;
- /*
- * Shortcut in the event we only get a single entry.
- */
- if (sg_len == 1) {
- memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
- return 1;
- }
+ buflen = 0;
+ for_each_sg(mq->bounce_sg, sg, sg_len, i)
+ buflen += sg->length;
- sg_init_one(mq->sg, mq->bounce_buf, 0);
-
- while (sg_len) {
- mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
- sg_len--;
- }
+ sg_init_one(mq->sg, mq->bounce_buf, buflen);
return 1;
}
+/*
+ * If writing, bounce the data to the buffer before the request
+ * is sent to the host driver
+ */
void mmc_queue_bounce_pre(struct mmc_queue *mq)
{
+ unsigned long flags;
+
if (!mq->bounce_buf)
return;
- if (mq->bounce_sg_len == 1)
- return;
if (rq_data_dir(mq->req) != WRITE)
return;
- copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+ local_irq_save(flags);
+ sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
+ mq->bounce_buf, mq->sg[0].length);
+ local_irq_restore(flags);
}
+/*
+ * If reading, bounce the data from the buffer after the request
+ * has been handled by the host driver
+ */
void mmc_queue_bounce_post(struct mmc_queue *mq)
{
+ unsigned long flags;
+
if (!mq->bounce_buf)
return;
- if (mq->bounce_sg_len == 1)
- return;
if (rq_data_dir(mq->req) != READ)
return;
- copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+ local_irq_save(flags);
+ sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
+ mq->bounce_buf, mq->sg[0].length);
+ local_irq_restore(flags);
}
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 3f15eb20489..99b20917cc0 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1043,7 +1043,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
goto out6;
}
- platform_set_drvdata(pdev, mmc);
+ platform_set_drvdata(pdev, host);
printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
" (mode=%s)\n", pdev->id, host->iobase,
@@ -1087,13 +1087,10 @@ out0:
static int __devexit au1xmmc_remove(struct platform_device *pdev)
{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct au1xmmc_host *host;
-
- if (mmc) {
- host = mmc_priv(mmc);
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
- mmc_remove_host(mmc);
+ if (host) {
+ mmc_remove_host(host->mmc);
#ifdef CONFIG_LEDS_CLASS
if (host->platdata && host->platdata->led)
@@ -1101,8 +1098,8 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
#endif
if (host->platdata && host->platdata->cd_setup &&
- !(mmc->caps & MMC_CAP_NEEDS_POLL))
- host->platdata->cd_setup(mmc, 0);
+ !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
+ host->platdata->cd_setup(host->mmc, 0);
au_writel(0, HOST_ENABLE(host));
au_writel(0, HOST_CONFIG(host));
@@ -1122,16 +1119,49 @@ static int __devexit au1xmmc_remove(struct platform_device *pdev)
release_resource(host->ioarea);
kfree(host->ioarea);
- mmc_free_host(mmc);
+ mmc_free_host(host->mmc);
+ platform_set_drvdata(pdev, NULL);
}
return 0;
}
+#ifdef CONFIG_PM
+static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = mmc_suspend_host(host->mmc, state);
+ if (ret)
+ return ret;
+
+ au_writel(0, HOST_CONFIG2(host));
+ au_writel(0, HOST_CONFIG(host));
+ au_writel(0xffffffff, HOST_STATUS(host));
+ au_writel(0, HOST_ENABLE(host));
+ au_sync();
+
+ return 0;
+}
+
+static int au1xmmc_resume(struct platform_device *pdev)
+{
+ struct au1xmmc_host *host = platform_get_drvdata(pdev);
+
+ au1xmmc_reset_controller(host);
+
+ return mmc_resume_host(host->mmc);
+}
+#else
+#define au1xmmc_suspend NULL
+#define au1xmmc_resume NULL
+#endif
+
static struct platform_driver au1xmmc_driver = {
.probe = au1xmmc_probe,
.remove = au1xmmc_remove,
- .suspend = NULL,
- .resume = NULL,
+ .suspend = au1xmmc_suspend,
+ .resume = au1xmmc_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index d39f5973886..a8e18fe5307 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -177,7 +177,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
if (dalgn)
DALGN |= (1 << host->dma);
else
- DALGN &= (1 << host->dma);
+ DALGN &= ~(1 << host->dma);
DDADR(host->dma) = host->sg_dma;
DCSR(host->dma) = DCSR_RUN;
}
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 6a1e4994b72..be550c26da6 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1331,21 +1331,30 @@ static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
return ret;
}
+static void s3cmci_shutdown(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct s3cmci_host *host = mmc_priv(mmc);
+
+ if (host->irq_cd >= 0)
+ free_irq(host->irq_cd, host);
+
+ mmc_remove_host(mmc);
+ clk_disable(host->clk);
+}
+
static int __devexit s3cmci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
- mmc_remove_host(mmc);
+ s3cmci_shutdown(pdev);
- clk_disable(host->clk);
clk_put(host->clk);
tasklet_disable(&host->pio_tasklet);
s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
- if (host->irq_cd >= 0)
- free_irq(host->irq_cd, host);
free_irq(host->irq, host);
iounmap(host->base);
@@ -1355,17 +1364,17 @@ static int __devexit s3cmci_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit s3cmci_probe_2410(struct platform_device *dev)
+static int __devinit s3cmci_2410_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 0);
}
-static int __devinit s3cmci_probe_2412(struct platform_device *dev)
+static int __devinit s3cmci_2412_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 1);
}
-static int __devinit s3cmci_probe_2440(struct platform_device *dev)
+static int __devinit s3cmci_2440_probe(struct platform_device *dev)
{
return s3cmci_probe(dev, 1);
}
@@ -1392,29 +1401,32 @@ static int s3cmci_resume(struct platform_device *dev)
#endif /* CONFIG_PM */
-static struct platform_driver s3cmci_driver_2410 = {
+static struct platform_driver s3cmci_2410_driver = {
.driver.name = "s3c2410-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2410,
+ .probe = s3cmci_2410_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_driver_2412 = {
+static struct platform_driver s3cmci_2412_driver = {
.driver.name = "s3c2412-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2412,
+ .probe = s3cmci_2412_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_driver_2440 = {
+static struct platform_driver s3cmci_2440_driver = {
.driver.name = "s3c2440-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_probe_2440,
+ .probe = s3cmci_2440_probe,
.remove = __devexit_p(s3cmci_remove),
+ .shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
@@ -1422,17 +1434,17 @@ static struct platform_driver s3cmci_driver_2440 = {
static int __init s3cmci_init(void)
{
- platform_driver_register(&s3cmci_driver_2410);
- platform_driver_register(&s3cmci_driver_2412);
- platform_driver_register(&s3cmci_driver_2440);
+ platform_driver_register(&s3cmci_2410_driver);
+ platform_driver_register(&s3cmci_2412_driver);
+ platform_driver_register(&s3cmci_2440_driver);
return 0;
}
static void __exit s3cmci_exit(void)
{
- platform_driver_unregister(&s3cmci_driver_2410);
- platform_driver_unregister(&s3cmci_driver_2412);
- platform_driver_unregister(&s3cmci_driver_2440);
+ platform_driver_unregister(&s3cmci_2410_driver);
+ platform_driver_unregister(&s3cmci_2412_driver);
+ platform_driver_unregister(&s3cmci_2440_driver);
}
module_init(s3cmci_init);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 17701c3da73..c3a5db72ddd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -173,119 +173,95 @@ static void sdhci_led_control(struct led_classdev *led,
* *
\*****************************************************************************/
-static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
-{
- return sg_virt(host->cur_sg);
-}
-
-static inline int sdhci_next_sg(struct sdhci_host* host)
-{
- /*
- * Skip to next SG entry.
- */
- host->cur_sg++;
- host->num_sg--;
-
- /*
- * Any entries left?
- */
- if (host->num_sg > 0) {
- host->offset = 0;
- host->remain = host->cur_sg->length;
- }
-
- return host->num_sg;
-}
-
static void sdhci_read_block_pio(struct sdhci_host *host)
{
- int blksize, chunk_remain;
- u32 data;
- char *buffer;
- int size;
+ unsigned long flags;
+ size_t blksize, len, chunk;
+ u32 scratch;
+ u8 *buf;
DBG("PIO reading\n");
blksize = host->data->blksz;
- chunk_remain = 0;
- data = 0;
+ chunk = 0;
- buffer = sdhci_sg_to_buffer(host) + host->offset;
+ local_irq_save(flags);
while (blksize) {
- if (chunk_remain == 0) {
- data = readl(host->ioaddr + SDHCI_BUFFER);
- chunk_remain = min(blksize, 4);
- }
+ if (!sg_miter_next(&host->sg_miter))
+ BUG();
- size = min(host->remain, chunk_remain);
+ len = min(host->sg_miter.length, blksize);
- chunk_remain -= size;
- blksize -= size;
- host->offset += size;
- host->remain -= size;
+ blksize -= len;
+ host->sg_miter.consumed = len;
- while (size) {
- *buffer = data & 0xFF;
- buffer++;
- data >>= 8;
- size--;
- }
+ buf = host->sg_miter.addr;
- if (host->remain == 0) {
- if (sdhci_next_sg(host) == 0) {
- BUG_ON(blksize != 0);
- return;
+ while (len) {
+ if (chunk == 0) {
+ scratch = readl(host->ioaddr + SDHCI_BUFFER);
+ chunk = 4;
}
- buffer = sdhci_sg_to_buffer(host);
+
+ *buf = scratch & 0xFF;
+
+ buf++;
+ scratch >>= 8;
+ chunk--;
+ len--;
}
}
+
+ sg_miter_stop(&host->sg_miter);
+
+ local_irq_restore(flags);
}
static void sdhci_write_block_pio(struct sdhci_host *host)
{
- int blksize, chunk_remain;
- u32 data;
- char *buffer;
- int bytes, size;
+ unsigned long flags;
+ size_t blksize, len, chunk;
+ u32 scratch;
+ u8 *buf;
DBG("PIO writing\n");
blksize = host->data->blksz;
- chunk_remain = 4;
- data = 0;
+ chunk = 0;
+ scratch = 0;
- bytes = 0;
- buffer = sdhci_sg_to_buffer(host) + host->offset;
+ local_irq_save(flags);
while (blksize) {
- size = min(host->remain, chunk_remain);
-
- chunk_remain -= size;
- blksize -= size;
- host->offset += size;
- host->remain -= size;
-
- while (size) {
- data >>= 8;
- data |= (u32)*buffer << 24;
- buffer++;
- size--;
- }
+ if (!sg_miter_next(&host->sg_miter))
+ BUG();
- if (chunk_remain == 0) {
- writel(data, host->ioaddr + SDHCI_BUFFER);
- chunk_remain = min(blksize, 4);
- }
+ len = min(host->sg_miter.length, blksize);
+
+ blksize -= len;
+ host->sg_miter.consumed = len;
+
+ buf = host->sg_miter.addr;
- if (host->remain == 0) {
- if (sdhci_next_sg(host) == 0) {
- BUG_ON(blksize != 0);
- return;
+ while (len) {
+ scratch |= (u32)*buf << (chunk * 8);
+
+ buf++;
+ chunk++;
+ len--;
+
+ if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
+ writel(scratch, host->ioaddr + SDHCI_BUFFER);
+ chunk = 0;
+ scratch = 0;
}
- buffer = sdhci_sg_to_buffer(host);
}
}
+
+ sg_miter_stop(&host->sg_miter);
+
+ local_irq_restore(flags);
}
static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -294,7 +270,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
BUG_ON(!host->data);
- if (host->num_sg == 0)
+ if (host->blocks == 0)
return;
if (host->data->flags & MMC_DATA_READ)
@@ -308,7 +284,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
else
sdhci_write_block_pio(host);
- if (host->num_sg == 0)
+ host->blocks--;
+ if (host->blocks == 0)
break;
}
@@ -389,6 +366,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
if (offset) {
if (data->flags & MMC_DATA_WRITE) {
buffer = sdhci_kmap_atomic(sg, &flags);
+ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
memcpy(align, buffer, offset);
sdhci_kunmap_atomic(buffer, &flags);
}
@@ -510,6 +488,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
size = 4 - (sg_dma_address(sg) & 0x3);
buffer = sdhci_kmap_atomic(sg, &flags);
+ WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
memcpy(buffer, align, size);
sdhci_kunmap_atomic(buffer, &flags);
@@ -687,7 +666,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
WARN_ON(1);
host->flags &= ~SDHCI_USE_DMA;
} else {
- WARN_ON(count != 1);
+ WARN_ON(sg_cnt != 1);
writel(sg_dma_address(data->sg),
host->ioaddr + SDHCI_DMA_ADDRESS);
}
@@ -711,11 +690,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
}
if (!(host->flags & SDHCI_REQ_USE_DMA)) {
- host->cur_sg = data->sg;
- host->num_sg = data->sg_len;
-
- host->offset = 0;
- host->remain = host->cur_sg->length;
+ sg_miter_start(&host->sg_miter,
+ data->sg, data->sg_len, SG_MITER_ATOMIC);
+ host->blocks = data->blocks;
}
/* We do not handle DMA boundaries, so set it to max (512 KiB) */
@@ -1581,9 +1558,15 @@ int sdhci_add_host(struct sdhci_host *host)
}
}
- /* XXX: Hack to get MMC layer to avoid highmem */
- if (!(host->flags & SDHCI_USE_DMA))
- mmc_dev(host->mmc)->dma_mask = NULL;
+ /*
+ * If we use DMA, then it's up to the caller to set the DMA
+ * mask, but PIO does not need the hw shim so we set a new
+ * mask here in that case.
+ */
+ if (!(host->flags & SDHCI_USE_DMA)) {
+ host->dma_mask = DMA_BIT_MASK(64);
+ mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+ }
host->max_clk =
(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 5bb35528176..a06bf8b8934 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -212,6 +212,7 @@ struct sdhci_host {
/* Internal data */
struct mmc_host *mmc; /* MMC structure */
+ u64 dma_mask; /* custom DMA mask */
#ifdef CONFIG_LEDS_CLASS
struct led_classdev led; /* LED control */
@@ -238,10 +239,8 @@ struct sdhci_host {
struct mmc_data *data; /* Current data request */
unsigned int data_early:1; /* Data finished before cmd */
- struct scatterlist *cur_sg; /* We're working on this */
- int num_sg; /* Entries left */
- int offset; /* Offset into current sg */
- int remain; /* Bytes left in current */
+ struct sg_mapping_iter sg_miter; /* SG state for PIO */
+ unsigned int blocks; /* remaining PIO blocks */
int sg_count; /* Mapped sg entries */
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 519d942e794..7b72a1b3611 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -241,6 +241,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
{
struct block_device *bdev;
struct block2mtd_dev *dev;
+ char *name;
if (!devname)
return NULL;
@@ -279,12 +280,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
/* Setup the MTD structure */
/* make the name contain the block device in */
- dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
+ name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
GFP_KERNEL);
- if (!dev->mtd.name)
+ if (!name)
goto devinit_err;
- sprintf(dev->mtd.name, "block2mtd: %s", devname);
+ sprintf(name, "block2mtd: %s", devname);
+ dev->mtd.name = name;
dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
dev->mtd.erasesize = erase_size;
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index c42f4b83f68..3fcf92130aa 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/major.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 129d429cd2d..aef9f4b687c 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -28,10 +28,13 @@ static void mtd_notify_add(struct mtd_info* mtd)
if (!mtd)
return;
- device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index);
+ device_create_drvdata(mtd_class, NULL,
+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+ NULL, "mtd%d", mtd->index);
- device_create(mtd_class, NULL,
- MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index);
+ device_create_drvdata(mtd_class, NULL,
+ MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+ NULL, "mtd%dro", mtd->index);
}
static void mtd_notify_remove(struct mtd_info* mtd)
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index cb663ef245d..fc8529bedfd 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -20,9 +20,11 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -30,20 +32,6 @@
#define GPIO_NAND_CS (11)
#define GPIO_NAND_RB (89)
-/* This macro needed to ensure in-order operation of GPIO and local
- * bus. Without both asm command and dummy uncached read there're
- * states when NAND access is broken. I've looked for such macro(s) in
- * include/asm-arm but found nothing approptiate.
- * dmac_clean_range is close, but is makes cache invalidation
- * unnecessary here and it cannot be used in module
- */
-#define DRAIN_WB() \
- do { \
- unsigned char dummy; \
- asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \
- dummy=*((unsigned char*)UNCACHED_ADDR); \
- } while(0)
-
/* MTD structure for CM-X270 board */
static struct mtd_info *cmx270_nand_mtd;
@@ -103,14 +91,14 @@ static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
static inline void nand_cs_on(void)
{
- GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO_NAND_CS, 0);
}
static void nand_cs_off(void)
{
- DRAIN_WB();
+ dsb();
- GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+ gpio_set_value(GPIO_NAND_CS, 1);
}
/*
@@ -122,7 +110,7 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
struct nand_chip* this = mtd->priv;
unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
- DRAIN_WB();
+ dsb();
if (ctrl & NAND_CTRL_CHANGE) {
if ( ctrl & NAND_ALE )
@@ -139,12 +127,12 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
nand_cs_off();
}
- DRAIN_WB();
+ dsb();
this->IO_ADDR_W = (void __iomem*)nandaddr;
if (dat != NAND_CMD_NONE)
writel((dat << 16), this->IO_ADDR_W);
- DRAIN_WB();
+ dsb();
}
/*
@@ -152,9 +140,9 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
*/
static int cmx270_device_ready(struct mtd_info *mtd)
{
- DRAIN_WB();
+ dsb();
- return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB));
+ return (gpio_get_value(GPIO_NAND_RB));
}
/*
@@ -168,20 +156,40 @@ static int cmx270_init(void)
int mtd_parts_nb = 0;
int ret;
+ if (!machine_is_armcore())
+ return -ENODEV;
+
+ ret = gpio_request(GPIO_NAND_CS, "NAND CS");
+ if (ret) {
+ pr_warning("CM-X270: failed to request NAND CS gpio\n");
+ return ret;
+ }
+
+ gpio_direction_output(GPIO_NAND_CS, 1);
+
+ ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
+ if (ret) {
+ pr_warning("CM-X270: failed to request NAND R/B gpio\n");
+ goto err_gpio_request;
+ }
+
+ gpio_direction_input(GPIO_NAND_RB);
+
/* Allocate memory for MTD device structure and private data */
cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip),
GFP_KERNEL);
if (!cmx270_nand_mtd) {
- printk("Unable to allocate CM-X270 NAND MTD device structure.\n");
- return -ENOMEM;
+ pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
+ ret = -ENOMEM;
+ goto err_kzalloc;
}
cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12);
if (!cmx270_nand_io) {
- printk("Unable to ioremap NAND device\n");
+ pr_debug("Unable to ioremap NAND device\n");
ret = -EINVAL;
- goto err1;
+ goto err_ioremap;
}
/* Get pointer to private data */
@@ -209,9 +217,9 @@ static int cmx270_init(void)
/* Scan to find existence of the device */
if (nand_scan (cmx270_nand_mtd, 1)) {
- printk(KERN_NOTICE "No NAND device\n");
+ pr_notice("No NAND device\n");
ret = -ENXIO;
- goto err2;
+ goto err_scan;
}
#ifdef CONFIG_MTD_CMDLINE_PARTS
@@ -229,18 +237,22 @@ static int cmx270_init(void)
}
/* Register the partitions */
- printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+ pr_notice("Using %s partition definition\n", part_type);
ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
if (ret)
- goto err2;
+ goto err_scan;
/* Return happy */
return 0;
-err2:
+err_scan:
iounmap(cmx270_nand_io);
-err1:
+err_ioremap:
kfree(cmx270_nand_mtd);
+err_kzalloc:
+ gpio_free(GPIO_NAND_RB);
+err_gpio_request:
+ gpio_free(GPIO_NAND_CS);
return ret;
@@ -255,6 +267,9 @@ static void cmx270_cleanup(void)
/* Release resources, unregister device */
nand_release(cmx270_nand_mtd);
+ gpio_free(GPIO_NAND_RB);
+ gpio_free(GPIO_NAND_CS);
+
iounmap(cmx270_nand_io);
/* Free the MTD device structure */
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index aabad8ce745..8db4e6b8948 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1010,7 +1010,7 @@ static int __devinit vortex_probe1(struct device *gendev,
static int printed_version;
int retval, print_info;
struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
- char *print_name = "3c59x";
+ const char *print_name = "3c59x";
struct pci_dev *pdev = NULL;
struct eisa_device *edev = NULL;
DECLARE_MAC_BUF(mac);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 75317a14ad1..8a5b0d293f7 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -98,7 +98,6 @@
#include <linux/compiler.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
@@ -120,11 +119,6 @@
NETIF_MSG_LINK)
-/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */
-#ifdef CONFIG_8139TOO_PIO
-#define USE_IO_OPS 1
-#endif
-
/* define to 1, 2 or 3 to enable copious debugging info */
#define RTL8139_DEBUG 0
@@ -156,6 +150,13 @@
static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Whether to use MMIO or PIO. Default to MMIO. */
+#ifdef CONFIG_8139TOO_PIO
+static int use_io = 1;
+#else
+static int use_io = 0;
+#endif
+
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
@@ -614,6 +615,8 @@ MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+module_param(use_io, int, 0);
+MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO");
module_param(multicast_filter_limit, int, 0);
module_param_array(media, int, NULL, 0);
module_param_array(full_duplex, int, NULL, 0);
@@ -709,13 +712,8 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
assert (tp->pci_dev != NULL);
pdev = tp->pci_dev;
-#ifdef USE_IO_OPS
- if (tp->mmio_addr)
- ioport_unmap (tp->mmio_addr);
-#else
if (tp->mmio_addr)
pci_iounmap (pdev, tp->mmio_addr);
-#endif /* USE_IO_OPS */
/* it's ok to call this even if we have no regions to free */
pci_release_regions (pdev);
@@ -790,32 +788,33 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
DPRINTK("PIO region size == 0x%02X\n", pio_len);
DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
-#ifdef USE_IO_OPS
- /* make sure PCI base addr 0 is PIO */
- if (!(pio_flags & IORESOURCE_IO)) {
- dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- /* check for weird/broken PCI region reporting */
- if (pio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
-#else
- /* make sure PCI base addr 1 is MMIO */
- if (!(mmio_flags & IORESOURCE_MEM)) {
- dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
- rc = -ENODEV;
- goto err_out;
- }
- if (mmio_len < RTL_MIN_IO_SIZE) {
- dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
- rc = -ENODEV;
- goto err_out;
+retry:
+ if (use_io) {
+ /* make sure PCI base addr 0 is PIO */
+ if (!(pio_flags & IORESOURCE_IO)) {
+ dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ /* check for weird/broken PCI region reporting */
+ if (pio_len < RTL_MIN_IO_SIZE) {
+ dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ } else {
+ /* make sure PCI base addr 1 is MMIO */
+ if (!(mmio_flags & IORESOURCE_MEM)) {
+ dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
+ if (mmio_len < RTL_MIN_IO_SIZE) {
+ dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
+ rc = -ENODEV;
+ goto err_out;
+ }
}
-#endif
rc = pci_request_regions (pdev, DRV_NAME);
if (rc)
@@ -825,28 +824,28 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* enable PCI bus-mastering */
pci_set_master (pdev);
-#ifdef USE_IO_OPS
- ioaddr = ioport_map(pio_start, pio_len);
- if (!ioaddr) {
- dev_err(&pdev->dev, "cannot map PIO, aborting\n");
- rc = -EIO;
- goto err_out;
- }
- dev->base_addr = pio_start;
- tp->mmio_addr = ioaddr;
- tp->regs_len = pio_len;
-#else
- /* ioremap MMIO region */
- ioaddr = pci_iomap(pdev, 1, 0);
- if (ioaddr == NULL) {
- dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
- rc = -EIO;
- goto err_out;
+ if (use_io) {
+ ioaddr = pci_iomap(pdev, 0, 0);
+ if (!ioaddr) {
+ dev_err(&pdev->dev, "cannot map PIO, aborting\n");
+ rc = -EIO;
+ goto err_out;
+ }
+ dev->base_addr = pio_start;
+ tp->regs_len = pio_len;
+ } else {
+ /* ioremap MMIO region */
+ ioaddr = pci_iomap(pdev, 1, 0);
+ if (ioaddr == NULL) {
+ dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n");
+ pci_release_regions(pdev);
+ use_io = 1;
+ goto retry;
+ }
+ dev->base_addr = (long) ioaddr;
+ tp->regs_len = mmio_len;
}
- dev->base_addr = (long) ioaddr;
tp->mmio_addr = ioaddr;
- tp->regs_len = mmio_len;
-#endif /* USE_IO_OPS */
/* Bring old chips out of low-power mode. */
RTL_W8 (HltClk, 'R');
@@ -952,6 +951,14 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
"Use the \"8139cp\" driver for improved performance and stability.\n");
}
+ if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
+ pdev->device == PCI_DEVICE_ID_REALTEK_8139 &&
+ pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS &&
+ pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) {
+ printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n");
+ use_io = 1;
+ }
+
i = rtl8139_init_board (pdev, &dev);
if (i < 0)
return i;
@@ -2381,20 +2388,24 @@ static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
np->msg_enable = datum;
}
-/* TODO: we are too slack to do reg dumping for pio, for now */
-#ifdef CONFIG_8139TOO_PIO
-#define rtl8139_get_regs_len NULL
-#define rtl8139_get_regs NULL
-#else
static int rtl8139_get_regs_len(struct net_device *dev)
{
- struct rtl8139_private *np = netdev_priv(dev);
+ struct rtl8139_private *np;
+ /* TODO: we are too slack to do reg dumping for pio, for now */
+ if (use_io)
+ return 0;
+ np = netdev_priv(dev);
return np->regs_len;
}
static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
{
- struct rtl8139_private *np = netdev_priv(dev);
+ struct rtl8139_private *np;
+
+ /* TODO: we are too slack to do reg dumping for pio, for now */
+ if (use_io)
+ return;
+ np = netdev_priv(dev);
regs->version = RTL_REGS_VER;
@@ -2402,7 +2413,6 @@ static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs,
memcpy_fromio(regbuf, np->mmio_addr, regs->len);
spin_unlock_irq(&np->lock);
}
-#endif /* CONFIG_8139TOO_MMIO */
static int rtl8139_get_sset_count(struct net_device *dev, int sset)
{
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3e5e64c33e1..fa533c27052 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1926,20 +1926,6 @@ config E1000
To compile this driver as a module, choose M here. The module
will be called e1000.
-config E1000_NAPI
- bool "Use Rx Polling (NAPI)"
- depends on E1000
- help
- NAPI is a new driver API designed to reduce CPU and interrupt load
- when the driver is receiving lots of packets from the card. It is
- still somewhat experimental and thus not yet enabled by default.
-
- If your estimated Rx load is 10kpps or more, or if the card will be
- deployed on potentially unfriendly networks (e.g. in a firewall),
- then say Y here.
-
- If in doubt, say N.
-
config E1000_DISABLE_PACKET_SPLIT
bool "Disable Packet Split for PCI express adapters"
depends on E1000
@@ -2304,6 +2290,17 @@ config ATL1
To compile this driver as a module, choose M here. The module
will be called atl1.
+config ATL1E
+ tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ select MII
+ help
+ This driver supports the Atheros L1E gigabit ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1e.
+
endif # NETDEV_1000
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4b17a9ab786..7629c901721 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_EHEA) += ehea/
obj-$(CONFIG_CAN) += can/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL1E) += atl1e/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_TEHUTI) += tehuti.o
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 1e39e78f177..ffae266e2d7 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -677,7 +677,7 @@ static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
{
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+ strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
}
static const struct ethtool_ops at91ether_ethtool_ops = {
@@ -820,7 +820,7 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
lp->skb = skb;
lp->skb_length = skb->len;
lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
- lp->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
/* Set address of the data in the Transmit Address register */
at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
@@ -843,34 +843,33 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev)
*/
static struct net_device_stats *at91ether_stats(struct net_device *dev)
{
- struct at91_private *lp = netdev_priv(dev);
int ale, lenerr, seqe, lcol, ecol;
if (netif_running(dev)) {
- lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
+ dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */
ale = at91_emac_read(AT91_EMAC_ALE);
- lp->stats.rx_frame_errors += ale; /* Alignment errors */
+ dev->stats.rx_frame_errors += ale; /* Alignment errors */
lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
- lp->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
+ dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */
seqe = at91_emac_read(AT91_EMAC_SEQE);
- lp->stats.rx_crc_errors += seqe; /* CRC error */
- lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
- lp->stats.rx_errors += (ale + lenerr + seqe
+ dev->stats.rx_crc_errors += seqe; /* CRC error */
+ dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */
+ dev->stats.rx_errors += (ale + lenerr + seqe
+ at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
- lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
- lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
- lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
- lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+ dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */
+ dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */
+ dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */
+ dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
lcol = at91_emac_read(AT91_EMAC_LCOL);
ecol = at91_emac_read(AT91_EMAC_ECOL);
- lp->stats.tx_window_errors += lcol; /* Late collisions */
- lp->stats.tx_aborted_errors += ecol; /* 16 collisions */
+ dev->stats.tx_window_errors += lcol; /* Late collisions */
+ dev->stats.tx_aborted_errors += ecol; /* 16 collisions */
- lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+ dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
}
- return &lp->stats;
+ return &dev->stats;
}
/*
@@ -896,16 +895,16 @@ static void at91ether_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev);
dev->last_rx = jiffies;
- lp->stats.rx_bytes += pktlen;
+ dev->stats.rx_bytes += pktlen;
netif_rx(skb);
}
else {
- lp->stats.rx_dropped += 1;
+ dev->stats.rx_dropped += 1;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
}
if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
- lp->stats.multicast++;
+ dev->stats.multicast++;
dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
@@ -934,7 +933,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
/* The TCOM bit is set even if the transmission failed. */
if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
- lp->stats.tx_errors += 1;
+ dev->stats.tx_errors += 1;
if (lp->skb) {
dev_kfree_skb_irq(lp->skb);
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
index a38fd2d053a..353f4dab62b 100644
--- a/drivers/net/arm/at91_ether.h
+++ b/drivers/net/arm/at91_ether.h
@@ -84,7 +84,6 @@ struct recv_desc_bufs
struct at91_private
{
- struct net_device_stats stats;
struct mii_if_info mii; /* ethtool support */
struct at91_eth_data board_data; /* board-specific configuration */
struct clk *ether_clk; /* clock */
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index ecd8fc6146e..7a14980f347 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -848,7 +848,7 @@ static int ep93xx_eth_probe(struct platform_device *pdev)
ep->res = request_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1,
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
if (ep->res == NULL) {
dev_err(&pdev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index e9d15eccad0..5c5f1e470d3 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -535,7 +535,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec)
if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
printk(KERN_ERR "%s: unable to read podule description string\n",
- ec->dev.bus_id);
+ dev_name(&ec->dev));
goto no_addr;
}
@@ -554,7 +554,7 @@ static int __init etherh_addr(char *addr, struct expansion_card *ec)
}
printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
- ec->dev.bus_id, cd.d.string);
+ dev_name(&ec->dev), cd.d.string);
no_addr:
return -ENODEV;
@@ -585,7 +585,7 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
{
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
- strlcpy(info->bus_info, dev->dev.parent->bus_id,
+ strlcpy(info->bus_info, dev_name(dev->dev.parent),
sizeof(info->bus_info));
}
diff --git a/drivers/net/atl1e/Makefile b/drivers/net/atl1e/Makefile
new file mode 100644
index 00000000000..bc11be824e7
--- /dev/null
+++ b/drivers/net/atl1e/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1E) += atl1e.o
+atl1e-objs += atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
new file mode 100644
index 00000000000..b645fa0f3f6
--- /dev/null
+++ b/drivers/net/atl1e/atl1e.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ATL1E_H_
+#define _ATL1E_H_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1e_hw.h"
+
+#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
+#define CMD_IO_SPACE 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER 0x0004
+
+#define BAR_0 0
+#define BAR_1 1
+#define BAR_5 5
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+
+#define SPEED_0 0xffff
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/* Error Codes */
+#define AT_ERR_EEPROM 1
+#define AT_ERR_PHY 2
+#define AT_ERR_CONFIG 3
+#define AT_ERR_PARAM 4
+#define AT_ERR_MAC_TYPE 5
+#define AT_ERR_PHY_TYPE 6
+#define AT_ERR_PHY_SPEED 7
+#define AT_ERR_PHY_RES 8
+#define AT_ERR_TIMEOUT 9
+
+#define MAX_JUMBO_FRAME_SIZE 0x2000
+
+#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd) \
+ _tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
+ (((_vlan) >> 9) & 8))
+
+#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan) \
+ _vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
+ (((_tdp) & 0x88) << 5))
+
+#define AT_MAX_RECEIVE_QUEUE 4
+#define AT_PAGE_NUM_PER_QUEUE 2
+
+#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG (5 * HZ)
+#define AT_MAX_INT_WORK 10
+#define AT_TWSI_EEPROM_TIMEOUT 100
+#define AT_HW_MAX_IDLE_DELAY 10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_REGS_LEN 75
+#define AT_EEPROM_LEN 512
+#define AT_ADV_MASK (ADVERTISE_10_HALF |\
+ ADVERTISE_10_FULL |\
+ ADVERTISE_100_HALF |\
+ ADVERTISE_100_FULL |\
+ ADVERTISE_1000_FULL)
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK 0x3FFF
+#define TPD_BUFLEN_SHIFT 0
+#define TPD_DMAINT_MASK 0x0001
+#define TPD_DMAINT_SHIFT 14
+#define TPD_PKTNT_MASK 0x0001
+#define TPD_PKTINT_SHIFT 15
+#define TPD_VLANTAG_MASK 0xFFFF
+#define TPD_VLAN_SHIFT 16
+
+/* tpd word 3 bits 0:4 */
+#define TPD_EOP_MASK 0x0001
+#define TPD_EOP_SHIFT 0
+#define TPD_IP_VERSION_MASK 0x0001
+#define TPD_IP_VERSION_SHIFT 1 /* 0 : IPV4, 1 : IPV6 */
+#define TPD_INS_VL_TAG_MASK 0x0001
+#define TPD_INS_VL_TAG_SHIFT 2
+#define TPD_CC_SEGMENT_EN_MASK 0x0001
+#define TPD_CC_SEGMENT_EN_SHIFT 3
+#define TPD_SEGMENT_EN_MASK 0x0001
+#define TPD_SEGMENT_EN_SHIFT 4
+
+/* tdp word 3 bits 5:7 if ip version is 0 */
+#define TPD_IP_CSUM_MASK 0x0001
+#define TPD_IP_CSUM_SHIFT 5
+#define TPD_TCP_CSUM_MASK 0x0001
+#define TPD_TCP_CSUM_SHIFT 6
+#define TPD_UDP_CSUM_MASK 0x0001
+#define TPD_UDP_CSUM_SHIFT 7
+
+/* tdp word 3 bits 5:7 if ip version is 1 */
+#define TPD_V6_IPHLLO_MASK 0x0007
+#define TPD_V6_IPHLLO_SHIFT 7
+
+/* tpd word 3 bits 8:9 bit */
+#define TPD_VL_TAGGED_MASK 0x0001
+#define TPD_VL_TAGGED_SHIFT 8
+#define TPD_ETHTYPE_MASK 0x0001
+#define TPD_ETHTYPE_SHIFT 9
+
+/* tdp word 3 bits 10:13 if ip version is 0 */
+#define TDP_V4_IPHL_MASK 0x000F
+#define TPD_V4_IPHL_SHIFT 10
+
+/* tdp word 3 bits 10:13 if ip version is 1 */
+#define TPD_V6_IPHLHI_MASK 0x000F
+#define TPD_V6_IPHLHI_SHIFT 10
+
+/* tpd word 3 bit 14:31 if segment enabled */
+#define TPD_TCPHDRLEN_MASK 0x000F
+#define TPD_TCPHDRLEN_SHIFT 14
+#define TPD_HDRFLAG_MASK 0x0001
+#define TPD_HDRFLAG_SHIFT 18
+#define TPD_MSS_MASK 0x1FFF
+#define TPD_MSS_SHIFT 19
+
+/* tdp word 3 bit 16:31 if custom csum enabled */
+#define TPD_PLOADOFFSET_MASK 0x00FF
+#define TPD_PLOADOFFSET_SHIFT 16
+#define TPD_CCSUMOFFSET_MASK 0x00FF
+#define TPD_CCSUMOFFSET_SHIFT 24
+
+struct atl1e_tpd_desc {
+ __le64 buffer_addr;
+ __le32 word2;
+ __le32 word3;
+};
+
+/* how about 0x2000 */
+#define MAX_TX_BUF_LEN 0x2000
+#define MAX_TX_BUF_SHIFT 13
+/*#define MAX_TX_BUF_LEN 0x3000 */
+
+/* rrs word 1 bit 0:31 */
+#define RRS_RX_CSUM_MASK 0xFFFF
+#define RRS_RX_CSUM_SHIFT 0
+#define RRS_PKT_SIZE_MASK 0x3FFF
+#define RRS_PKT_SIZE_SHIFT 16
+#define RRS_CPU_NUM_MASK 0x0003
+#define RRS_CPU_NUM_SHIFT 30
+
+#define RRS_IS_RSS_IPV4 0x0001
+#define RRS_IS_RSS_IPV4_TCP 0x0002
+#define RRS_IS_RSS_IPV6 0x0004
+#define RRS_IS_RSS_IPV6_TCP 0x0008
+#define RRS_IS_IPV6 0x0010
+#define RRS_IS_IP_FRAG 0x0020
+#define RRS_IS_IP_DF 0x0040
+#define RRS_IS_802_3 0x0080
+#define RRS_IS_VLAN_TAG 0x0100
+#define RRS_IS_ERR_FRAME 0x0200
+#define RRS_IS_IPV4 0x0400
+#define RRS_IS_UDP 0x0800
+#define RRS_IS_TCP 0x1000
+#define RRS_IS_BCAST 0x2000
+#define RRS_IS_MCAST 0x4000
+#define RRS_IS_PAUSE 0x8000
+
+#define RRS_ERR_BAD_CRC 0x0001
+#define RRS_ERR_CODE 0x0002
+#define RRS_ERR_DRIBBLE 0x0004
+#define RRS_ERR_RUNT 0x0008
+#define RRS_ERR_RX_OVERFLOW 0x0010
+#define RRS_ERR_TRUNC 0x0020
+#define RRS_ERR_IP_CSUM 0x0040
+#define RRS_ERR_L4_CSUM 0x0080
+#define RRS_ERR_LENGTH 0x0100
+#define RRS_ERR_DES_ADDR 0x0200
+
+struct atl1e_recv_ret_status {
+ u16 seq_num;
+ u16 hash_lo;
+ __le32 word1;
+ u16 pkt_flag;
+ u16 err_flag;
+ u16 hash_hi;
+ u16 vtag;
+};
+
+enum atl1e_dma_req_block {
+ atl1e_dma_req_128 = 0,
+ atl1e_dma_req_256 = 1,
+ atl1e_dma_req_512 = 2,
+ atl1e_dma_req_1024 = 3,
+ atl1e_dma_req_2048 = 4,
+ atl1e_dma_req_4096 = 5
+};
+
+enum atl1e_rrs_type {
+ atl1e_rrs_disable = 0,
+ atl1e_rrs_ipv4 = 1,
+ atl1e_rrs_ipv4_tcp = 2,
+ atl1e_rrs_ipv6 = 4,
+ atl1e_rrs_ipv6_tcp = 8
+};
+
+enum atl1e_nic_type {
+ athr_l1e = 0,
+ athr_l2e_revA = 1,
+ athr_l2e_revB = 2
+};
+
+struct atl1e_hw_stats {
+ /* rx */
+ unsigned long rx_ok; /* The number of good packet received. */
+ unsigned long rx_bcast; /* The number of good broadcast packet received. */
+ unsigned long rx_mcast; /* The number of good multicast packet received. */
+ unsigned long rx_pause; /* The number of Pause packet received. */
+ unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */
+ unsigned long rx_fcs_err; /* The number of packets with bad FCS. */
+ unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */
+ unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
+ unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
+ unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
+ unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
+ unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
+ unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
+ unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
+ unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+ unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+ unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+ unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+ unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+ unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
+ unsigned long rx_align_err; /* Alignment Error */
+ unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+ unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+ unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */
+
+ /* tx */
+ unsigned long tx_ok; /* The number of good packet transmitted. */
+ unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */
+ unsigned long tx_mcast; /* The number of good multicast packet transmitted. */
+ unsigned long tx_pause; /* The number of Pause packet transmitted. */
+ unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
+ unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
+ unsigned long tx_defer; /* The number of packets transmitted that is deferred. */
+ unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
+ unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
+ unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+ unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+ unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+ unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+ unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+ unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+ unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
+ unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+ unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */
+ unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
+ unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+ unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+ unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
+ unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
+ unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
+ unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1e_hw {
+ u8 __iomem *hw_addr; /* inner register address */
+ resource_size_t mem_rang;
+ struct atl1e_adapter *adapter;
+ enum atl1e_nic_type nic_type;
+ u16 device_id;
+ u16 vendor_id;
+ u16 subsystem_id;
+ u16 subsystem_vendor_id;
+ u8 revision_id;
+ u16 pci_cmd_word;
+ u8 mac_addr[ETH_ALEN];
+ u8 perm_mac_addr[ETH_ALEN];
+ u8 preamble_len;
+ u16 max_frame_size;
+ u16 rx_jumbo_th;
+ u16 tx_jumbo_th;
+
+ u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR 0
+#define MEDIA_TYPE_100M_FULL 1
+#define MEDIA_TYPE_100M_HALF 2
+#define MEDIA_TYPE_10M_FULL 3
+#define MEDIA_TYPE_10M_HALF 4
+
+ u16 autoneg_advertised;
+#define ADVERTISE_10_HALF 0x0001
+#define ADVERTISE_10_FULL 0x0002
+#define ADVERTISE_100_HALF 0x0004
+#define ADVERTISE_100_FULL 0x0008
+#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL 0x0020
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ u16 imt; /* Interrupt Moderator timer ( 2us resolution) */
+ u16 ict; /* Interrupt Clear timer (2us resolution) */
+ u32 smb_timer;
+ u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+ interrupt request */
+ u16 tpd_thresh;
+ u16 rx_count_down; /* 2us resolution */
+ u16 tx_count_down;
+
+ u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */
+ enum atl1e_rrs_type rrs_type;
+ u32 base_cpu;
+ u32 indirect_tab;
+
+ enum atl1e_dma_req_block dmar_block;
+ enum atl1e_dma_req_block dmaw_block;
+ u8 dmaw_dly_cnt;
+ u8 dmar_dly_cnt;
+
+ bool phy_configured;
+ bool re_autoneg;
+ bool emi_ca;
+};
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1e_tx_buffer {
+ struct sk_buff *skb;
+ u16 length;
+ dma_addr_t dma;
+};
+
+struct atl1e_rx_page {
+ dma_addr_t dma; /* receive rage DMA address */
+ u8 *addr; /* receive rage virtual address */
+ dma_addr_t write_offset_dma; /* the DMA address which contain the
+ receive data offset in the page */
+ u32 *write_offset_addr; /* the virtaul address which contain
+ the receive data offset in the page */
+ u32 read_offset; /* the offset where we have read */
+};
+
+struct atl1e_rx_page_desc {
+ struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE];
+ u8 rx_using;
+ u16 rx_nxseq;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1e_tx_ring {
+ struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */
+ dma_addr_t dma; /* descriptor ring physical address */
+ u16 count; /* the count of transmit rings */
+ rwlock_t tx_lock;
+ u16 next_to_use;
+ atomic_t next_to_clean;
+ struct atl1e_tx_buffer *tx_buffer;
+ dma_addr_t cmb_dma;
+ u32 *cmb;
+};
+
+/* receive packet descriptor ring */
+struct atl1e_rx_ring {
+ void *desc;
+ dma_addr_t dma;
+ int size;
+ u32 page_size; /* bytes length of rxf page */
+ u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */
+ struct atl1e_rx_page_desc rx_page_desc[AT_MAX_RECEIVE_QUEUE];
+};
+
+/* board specific private data structure */
+struct atl1e_adapter {
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct vlan_group *vlgrp;
+ struct napi_struct napi;
+ struct mii_if_info mii; /* MII interface info */
+ struct atl1e_hw hw;
+ struct atl1e_hw_stats hw_stats;
+ struct net_device_stats net_stats;
+
+ bool have_msi;
+ u32 wol;
+ u16 link_speed;
+ u16 link_duplex;
+
+ spinlock_t mdio_lock;
+ spinlock_t tx_lock;
+ atomic_t irq_sem;
+
+ struct work_struct reset_task;
+ struct work_struct link_chg_task;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_config_timer;
+
+ /* All Descriptor memory */
+ dma_addr_t ring_dma;
+ void *ring_vir_addr;
+ int ring_size;
+
+ struct atl1e_tx_ring tx_ring;
+ struct atl1e_rx_ring rx_ring;
+ int num_rx_queues;
+ unsigned long flags;
+#define __AT_TESTING 0x0001
+#define __AT_RESETTING 0x0002
+#define __AT_DOWN 0x0003
+
+ u32 bd_number; /* board number;*/
+ u32 pci_state[16];
+ u32 *config_space;
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+ writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+ readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg) ( \
+ readl((a)->hw_addr + reg))
+
+#define AT_WRITE_REGB(a, reg, value) (\
+ writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+ readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+ writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+ readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+ writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+ readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1e_driver_name[];
+extern char atl1e_driver_version[];
+
+extern void atl1e_check_options(struct atl1e_adapter *adapter);
+extern int atl1e_up(struct atl1e_adapter *adapter);
+extern void atl1e_down(struct atl1e_adapter *adapter);
+extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
+extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
+extern void atl1e_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1_E_H_ */
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c
new file mode 100644
index 00000000000..cdc3b85b10b
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_ethtool.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "atl1e.h"
+
+static int atl1e_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_TP);
+ if (hw->nic_type == athr_l1e)
+ ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+ ecmd->advertising = ADVERTISED_TP;
+
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->advertising |= hw->autoneg_advertised;
+
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = 0;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (adapter->link_speed != SPEED_0) {
+ ecmd->speed = adapter->link_speed;
+ if (adapter->link_duplex == FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ ecmd->autoneg = AUTONEG_ENABLE;
+ return 0;
+}
+
+static int atl1e_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ u16 adv4, adv9;
+
+ if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+ if (hw->nic_type == athr_l1e) {
+ hw->autoneg_advertised =
+ ecmd->advertising & AT_ADV_MASK;
+ } else {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+ } else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ } else {
+ hw->autoneg_advertised =
+ ecmd->advertising & AT_ADV_MASK;
+ }
+ ecmd->advertising = hw->autoneg_advertised |
+ ADVERTISED_TP | ADVERTISED_Autoneg;
+
+ adv4 = hw->mii_autoneg_adv_reg & ~MII_AR_SPEED_MASK;
+ adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
+ if (hw->autoneg_advertised & ADVERTISE_10_HALF)
+ adv4 |= MII_AR_10T_HD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_10_FULL)
+ adv4 |= MII_AR_10T_FD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_100_HALF)
+ adv4 |= MII_AR_100TX_HD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_100_FULL)
+ adv4 |= MII_AR_100TX_FD_CAPS;
+ if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
+ adv9 |= MII_AT001_CR_1000T_FD_CAPS;
+
+ if (adv4 != hw->mii_autoneg_adv_reg ||
+ adv9 != hw->mii_1000t_ctrl_reg) {
+ hw->mii_autoneg_adv_reg = adv4;
+ hw->mii_1000t_ctrl_reg = adv9;
+ hw->re_autoneg = true;
+ }
+
+ } else {
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return -EINVAL;
+ }
+
+ /* reset the link */
+
+ if (netif_running(adapter->netdev)) {
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ } else
+ atl1e_reset_hw(&adapter->hw);
+
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ return 0;
+}
+
+static u32 atl1e_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl1e_get_msglevel(struct net_device *netdev)
+{
+#ifdef DBG
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static void atl1e_set_msglevel(struct net_device *netdev, u32 data)
+{
+}
+
+static int atl1e_get_regs_len(struct net_device *netdev)
+{
+ return AT_REGS_LEN * sizeof(u32);
+}
+
+static void atl1e_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *regs_buff = p;
+ u16 phy_data;
+
+ memset(p, 0, AT_REGS_LEN * sizeof(u32));
+
+ regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+ regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP);
+ regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG);
+ regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL);
+ regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
+ regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL);
+ regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT);
+ regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
+ regs_buff[8] = AT_READ_REG(hw, REG_GPHY_CTRL);
+ regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER);
+ regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS);
+ regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL);
+ regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK);
+ regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL);
+ regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG);
+ regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4);
+ regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE);
+ regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4);
+ regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
+ regs_buff[20] = AT_READ_REG(hw, REG_MTU);
+ regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL);
+ regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR);
+ regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
+ regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
+ regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
+ regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
+ regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
+ regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
+
+ atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
+ regs_buff[73] = (u32)phy_data;
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ regs_buff[74] = (u32)phy_data;
+}
+
+static int atl1e_get_eeprom_len(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (!atl1e_check_eeprom_exist(&adapter->hw))
+ return AT_EEPROM_LEN;
+ else
+ return 0;
+}
+
+static int atl1e_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ int first_dword, last_dword;
+ int ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EINVAL;
+
+ if (atl1e_check_eeprom_exist(hw)) /* not exist */
+ return -EINVAL;
+
+ eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+ eeprom_buff = kmalloc(sizeof(u32) *
+ (last_dword - first_dword + 1), GFP_KERNEL);
+ if (eeprom_buff == NULL)
+ return -ENOMEM;
+
+ for (i = first_dword; i < last_dword; i++) {
+ if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+ kfree(eeprom_buff);
+ return -EIO;
+ }
+ }
+
+ memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+ eeprom->len);
+ kfree(eeprom_buff);
+
+ return ret_val;
+}
+
+static int atl1e_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 *eeprom_buff;
+ u32 *ptr;
+ int first_dword, last_dword;
+ int ret_val = 0;
+ int i;
+
+ if (eeprom->len == 0)
+ return -EOPNOTSUPP;
+
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ return -EINVAL;
+
+ first_dword = eeprom->offset >> 2;
+ last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+ eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
+ if (eeprom_buff == NULL)
+ return -ENOMEM;
+
+ ptr = (u32 *)eeprom_buff;
+
+ if (eeprom->offset & 3) {
+ /* need read/modify/write of first changed EEPROM word */
+ /* only the second byte of the word is being modified */
+ if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
+ ret_val = -EIO;
+ goto out;
+ }
+ ptr++;
+ }
+ if (((eeprom->offset + eeprom->len) & 3)) {
+ /* need read/modify/write of last changed EEPROM word */
+ /* only the first byte of the word is being modified */
+
+ if (!atl1e_read_eeprom(hw, last_dword * 4,
+ &(eeprom_buff[last_dword - first_dword]))) {
+ ret_val = -EIO;
+ goto out;
+ }
+ }
+
+ /* Device's eeprom is always little-endian, word addressable */
+ memcpy(ptr, bytes, eeprom->len);
+
+ for (i = 0; i < last_dword - first_dword + 1; i++) {
+ if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
+ eeprom_buff[i])) {
+ ret_val = -EIO;
+ goto out;
+ }
+ }
+out:
+ kfree(eeprom_buff);
+ return ret_val;
+}
+
+static void atl1e_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ strncpy(drvinfo->driver, atl1e_driver_name, 32);
+ strncpy(drvinfo->version, atl1e_driver_version, 32);
+ strncpy(drvinfo->fw_version, "L1e", 32);
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+ drvinfo->n_stats = 0;
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = atl1e_get_regs_len(netdev);
+ drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
+}
+
+static void atl1e_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_MAGIC | WAKE_PHY;
+ wol->wolopts = 0;
+
+ if (adapter->wol & AT_WUFC_EX)
+ wol->wolopts |= WAKE_UCAST;
+ if (adapter->wol & AT_WUFC_MC)
+ wol->wolopts |= WAKE_MCAST;
+ if (adapter->wol & AT_WUFC_BC)
+ wol->wolopts |= WAKE_BCAST;
+ if (adapter->wol & AT_WUFC_MAG)
+ wol->wolopts |= WAKE_MAGIC;
+ if (adapter->wol & AT_WUFC_LNKC)
+ wol->wolopts |= WAKE_PHY;
+
+ return;
+}
+
+static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+ WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+ return -EOPNOTSUPP;
+ /* these settings will always override what we currently have */
+ adapter->wol = 0;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ adapter->wol |= AT_WUFC_MAG;
+ if (wol->wolopts & WAKE_PHY)
+ adapter->wol |= AT_WUFC_LNKC;
+
+ return 0;
+}
+
+static int atl1e_nway_reset(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ if (netif_running(netdev))
+ atl1e_reinit_locked(adapter);
+ return 0;
+}
+
+static struct ethtool_ops atl1e_ethtool_ops = {
+ .get_settings = atl1e_get_settings,
+ .set_settings = atl1e_set_settings,
+ .get_drvinfo = atl1e_get_drvinfo,
+ .get_regs_len = atl1e_get_regs_len,
+ .get_regs = atl1e_get_regs,
+ .get_wol = atl1e_get_wol,
+ .set_wol = atl1e_set_wol,
+ .get_msglevel = atl1e_get_msglevel,
+ .set_msglevel = atl1e_set_msglevel,
+ .nway_reset = atl1e_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = atl1e_get_eeprom_len,
+ .get_eeprom = atl1e_get_eeprom,
+ .set_eeprom = atl1e_set_eeprom,
+ .get_tx_csum = atl1e_get_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+ .get_tso = ethtool_op_get_tso,
+#endif
+};
+
+void atl1e_set_ethtool_ops(struct net_device *netdev)
+{
+ SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
+}
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
new file mode 100644
index 00000000000..949e75358bf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -0,0 +1,664 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1e.h"
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+ u32 value;
+
+ value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+ }
+ value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32)hw->mac_addr[2]) << 24) |
+ (((u32)hw->mac_addr[3]) << 16) |
+ (((u32)hw->mac_addr[4]) << 8) |
+ (((u32)hw->mac_addr[5])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+ /* hight dword */
+ value = (((u32)hw->mac_addr[0]) << 8) |
+ (((u32)hw->mac_addr[1])) ;
+ AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+ u32 addr[2];
+ u32 i;
+ u32 twsi_ctrl_data;
+ u8 eth_addr[ETH_ALEN];
+
+ if (is_valid_ether_addr(hw->perm_mac_addr))
+ return 0;
+
+ /* init */
+ addr[0] = addr[1] = 0;
+
+ if (!atl1e_check_eeprom_exist(hw)) {
+ /* eeprom exist */
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+ AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+ for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+ msleep(10);
+ twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+ if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+ break;
+ }
+ if (i >= AT_TWSI_EEPROM_TIMEOUT)
+ return AT_ERR_TIMEOUT;
+ }
+
+ /* maybe MAC-address is from BIOS */
+ addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+ addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+ *(u32 *) &eth_addr[2] = swab32(addr[0]);
+ *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+
+ return AT_ERR_EEPROM;
+}
+
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
+{
+ return true;
+}
+
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
+{
+ int i;
+ u32 control;
+
+ if (offset & 3)
+ return false; /* address do not align */
+
+ AT_WRITE_REG(hw, REG_VPD_DATA, 0);
+ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+ AT_WRITE_REG(hw, REG_VPD_CAP, control);
+
+ for (i = 0; i < 10; i++) {
+ msleep(2);
+ control = AT_READ_REG(hw, REG_VPD_CAP);
+ if (control & VPD_CAP_VPD_FLAG)
+ break;
+ }
+ if (control & VPD_CAP_VPD_FLAG) {
+ *p_value = AT_READ_REG(hw, REG_VPD_DATA);
+ return true;
+ }
+ return false; /* timeout */
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+ GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_get_permanent_address(hw);
+ if (err)
+ return AT_ERR_EEPROM;
+ memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+ return 0;
+}
+
+/*
+ * atl1e_hash_mc_addr
+ * purpose
+ * set hash value for a multicast address
+ * hash calcu processing :
+ * 1. calcu 32bit CRC for multicast address
+ * 2. reverse crc with MSB to LSB
+ */
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
+{
+ u32 crc32;
+ u32 value = 0;
+ int i;
+
+ crc32 = ether_crc_le(6, mc_addr);
+ crc32 = ~crc32;
+ for (i = 0; i < 32; i++)
+ value |= (((crc32 >> i) & 1) << (31 - i));
+
+ return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
+{
+ u32 hash_bit, hash_reg;
+ u32 mta;
+
+ /*
+ * The HASH Table is a register array of 2 32-bit registers.
+ * It is treated like an array of 64 bits. We want to set
+ * bit BitArray[hash_value]. So we figure out what register
+ * the bit is in, read it, OR in the new bit, then write
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
+ * register are determined by the lower 5 bits of the value.
+ */
+ hash_reg = (hash_value >> 31) & 0x1;
+ hash_bit = (hash_value >> 26) & 0x1F;
+
+ mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+ mta |= (1 << hash_bit);
+
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16)val;
+ return 0;
+ }
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START |
+ MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+ AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+ wmb();
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ wmb();
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return 0;
+
+ return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+ u32 value;
+ /* comment 2lines below to save more power when sususpend
+ value = LTSSM_TEST_MODE_DEF;
+ AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+ */
+
+ /* pcie flow control mode change */
+ value = AT_READ_REG(hw, 0x1008);
+ value |= 0x8000;
+ AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+ s32 ret_val;
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ if (0 != hw->mii_autoneg_adv_reg)
+ return 0;
+ /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+ mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * Need to parse autoneg_advertised and set up
+ * the appropriate PHY registers. First we will parse for
+ * autoneg_advertised software override. Since we can advertise
+ * a plethora of combinations, we need to check each bit
+ * individually.
+ */
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+ /*
+ * Need to parse MediaType and setup the
+ * appropriate PHY registers.
+ */
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ hw->autoneg_advertised = ADVERTISE_10_HALF |
+ ADVERTISE_10_FULL |
+ ADVERTISE_100_HALF |
+ ADVERTISE_100_FULL;
+ if (hw->nic_type == athr_l1e) {
+ mii_1000t_ctrl_reg |=
+ MII_AT001_CR_1000T_FD_CAPS;
+ hw->autoneg_advertised |= ADVERTISE_1000_FULL;
+ }
+ break;
+
+ case MEDIA_TYPE_100M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_FULL;
+ break;
+
+ case MEDIA_TYPE_100M_HALF:
+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_100_HALF;
+ break;
+
+ case MEDIA_TYPE_10M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_FULL;
+ break;
+
+ default:
+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+ hw->autoneg_advertised = ADVERTISE_10_HALF;
+ break;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+ int ret_val;
+ u16 phy_data;
+
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /**************************************
+ * pcie serdes link may be down !
+ **************************************/
+ for (i = 0; i < 25; i++) {
+ msleep(1);
+ val = AT_READ_REG(hw, REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+ dev_err(&pdev->dev,
+ "pcie linkdown at least for 25ms\n");
+ return ret_val;
+ }
+
+ dev_err(&pdev->dev, "pcie linkup after %d ms\n", i);
+ }
+ return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+ s32 ret_val;
+ u16 phy_val;
+
+ if (hw->phy_configured) {
+ if (hw->re_autoneg) {
+ hw->re_autoneg = false;
+ return atl1e_restart_autoneg(hw);
+ }
+ return 0;
+ }
+
+ /* RESET GPHY Core */
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+ msleep(2);
+ AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+ GPHY_CTRL_EXT_RESET);
+ msleep(2);
+
+ /* patches */
+ /* p1. eable hibernation mode */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+ if (ret_val)
+ return ret_val;
+ /* p2. set Class A/B for all modes */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ phy_val = 0x02ef;
+ /* remove Class AB */
+ /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+ if (ret_val)
+ return ret_val;
+ /* p3. 10B ??? */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+ if (ret_val)
+ return ret_val;
+ /* p4. 1000T power */
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+ if (ret_val)
+ return ret_val;
+ ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+ if (ret_val)
+ return ret_val;
+
+ msleep(1);
+
+ /*Enable PHY LinkChange Interrupt */
+ ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error enable PHY linkChange Interrupt\n");
+ return ret_val;
+ }
+ /* setup AutoNeg parameters */
+ ret_val = atl1e_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+ dev_dbg(&pdev->dev, "Restarting Auto-Neg");
+ ret_val = atl1e_phy_commit(hw);
+ if (ret_val) {
+ dev_err(&pdev->dev, "Error Resetting the phy");
+ return ret_val;
+ }
+
+ hw->phy_configured = true;
+
+ return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0 or idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+ struct pci_dev *pdev = adapter->pdev;
+
+ u32 idle_status_data = 0;
+ u16 pci_cfg_cmd_word = 0;
+ int timeout = 0;
+
+ /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+ pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+ if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
+ CMD_MEMORY_SPACE | CMD_BUS_MASTER))
+ != (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
+ pci_cfg_cmd_word |= (CMD_IO_SPACE |
+ CMD_MEMORY_SPACE | CMD_BUS_MASTER);
+ pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
+ }
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ AT_WRITE_REG(hw, REG_MASTER_CTRL,
+ MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+ wmb();
+ msleep(1);
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+ idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+ if (idle_status_data == 0)
+ break;
+ msleep(1);
+ cpu_relax();
+ }
+
+ if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+ dev_err(&pdev->dev,
+ "MAC state machine cann't be idle since"
+ " disabled for 10ms second\n");
+ return AT_ERR_TIMEOUT;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+ s32 ret_val = 0;
+
+ atl1e_init_pcie(hw);
+
+ /* Zero out the Multicast HASH table */
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ ret_val = atl1e_phy_init(hw);
+
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+ int err;
+ u16 phy_data;
+
+ /* Read PHY Specific Status Register (17) */
+ err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+ if (err)
+ return err;
+
+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+ return AT_ERR_PHY_RES;
+
+ switch (phy_data & MII_AT001_PSSR_SPEED) {
+ case MII_AT001_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_AT001_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_AT001_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ return AT_ERR_PHY_SPEED;
+ break;
+ }
+
+ if (phy_data & MII_AT001_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+ int err = 0;
+
+ err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ if (err)
+ return err;
+
+ if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+ err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+ hw->mii_1000t_ctrl_reg);
+ if (err)
+ return err;
+ }
+
+ err = atl1e_write_phy_reg(hw, MII_BMCR,
+ MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+ MII_CR_RESTART_AUTO_NEG);
+ return err;
+}
+
diff --git a/drivers/net/atl1e/atl1e_hw.h b/drivers/net/atl1e/atl1e_hw.h
new file mode 100644
index 00000000000..5ea2f4d86cf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.h
@@ -0,0 +1,793 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ATHL1E_HW_H_
+#define _ATHL1E_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1e_adapter;
+struct atl1e_hw;
+
+/* function prototype */
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_init_hw(struct atl1e_hw *hw);
+s32 atl1e_phy_commit(struct atl1e_hw *hw);
+s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
+s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
+s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
+s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_init(struct atl1e_hw *hw);
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
+void atl1e_force_ps(struct atl1e_hw *hw);
+s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
+
+/* register definition */
+#define REG_PM_CTRLSTAT 0x44
+
+#define REG_PCIE_CAP_LIST 0x58
+
+#define REG_DEVICE_CAP 0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0
+
+#define REG_DEVICE_CTRL 0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12
+
+#define REG_VPD_CAP 0x6C
+#define VPD_CAP_ID_MASK 0xff
+#define VPD_CAP_ID_SHIFT 0
+#define VPD_CAP_NEXT_PTR_MASK 0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT 8
+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT 16
+#define VPD_CAP_VPD_FLAG 0x80000000
+
+#define REG_VPD_DATA 0x70
+
+#define REG_SPI_FLASH_CTRL 0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
+#define SPI_FLASH_CTRL_STS_WEN 0x2
+#define SPI_FLASH_CTRL_STS_WPEN 0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
+#define SPI_FLASH_CTRL_INS_MASK 0x7
+#define SPI_FLASH_CTRL_INS_SHIFT 8
+#define SPI_FLASH_CTRL_START 0x800
+#define SPI_FLASH_CTRL_EN_VPD 0x2000
+#define SPI_FLASH_CTRL_LDSTART 0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
+
+#define REG_SPI_ADDR 0x204
+
+#define REG_SPI_DATA 0x208
+
+#define REG_SPI_FLASH_CONFIG 0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
+
+
+#define REG_SPI_FLASH_OP_PROGRAM 0x210
+#define REG_SPI_FLASH_OP_SC_ERASE 0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID 0x213
+#define REG_SPI_FLASH_OP_WREN 0x214
+#define REG_SPI_FLASH_OP_RDSR 0x215
+#define REG_SPI_FLASH_OP_WRSR 0x216
+#define REG_SPI_FLASH_OP_READ 0x217
+
+#define REG_TWSI_CTRL 0x218
+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT 0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
+#define TWSI_CTRL_SW_LDSTART 0x800
+#define TWSI_CTRL_HW_LDSTART 0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
+#define TWSI_CTRL_LD_EXIST 0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
+#define TWSI_CTRL_FREQ_SEL_100K 0
+#define TWSI_CTRL_FREQ_SEL_200K 1
+#define TWSI_CTRL_FREQ_SEL_300K 2
+#define TWSI_CTRL_FREQ_SEL_400K 3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
+
+
+#define REG_PCIE_DEV_MISC_CTRL 0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
+
+#define REG_PCIE_PHYMISC 0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET 0x4
+
+#define REG_LTSSM_TEST_MODE 0x12FC
+#define LTSSM_TEST_MODE_DEF 0xE000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL 0x1400
+#define MASTER_CTRL_SOFT_RST 0x1
+#define MASTER_CTRL_MTIMER_EN 0x2
+#define MASTER_CTRL_ITIMER_EN 0x4
+#define MASTER_CTRL_MANUAL_INT 0x8
+#define MASTER_CTRL_ITIMER2_EN 0x20
+#define MASTER_CTRL_INT_RDCLR 0x40
+#define MASTER_CTRL_LED_MODE 0x200
+#define MASTER_CTRL_REV_NUM_SHIFT 16
+#define MASTER_CTRL_REV_NUM_MASK 0xff
+#define MASTER_CTRL_DEV_ID_SHIFT 24
+#define MASTER_CTRL_DEV_ID_MASK 0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT 0x1404
+
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT 0x1408 /* w */
+#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */
+
+
+#define REG_GPHY_CTRL 0x140C
+#define GPHY_CTRL_EXT_RESET 1
+#define GPHY_CTRL_PIPE_MOD 2
+#define GPHY_CTRL_TEST_MODE_MASK 3
+#define GPHY_CTRL_TEST_MODE_SHIFT 2
+#define GPHY_CTRL_BERT_START 0x10
+#define GPHY_CTRL_GATE_25M_EN 0x20
+#define GPHY_CTRL_LPW_EXIT 0x40
+#define GPHY_CTRL_PHY_IDDQ 0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS 0x100
+#define GPHY_CTRL_PCLK_SEL_DIS 0x200
+#define GPHY_CTRL_HIB_EN 0x400
+#define GPHY_CTRL_HIB_PULSE 0x800
+#define GPHY_CTRL_SEL_ANA_RST 0x1000
+#define GPHY_CTRL_PHY_PLL_ON 0x2000
+#define GPHY_CTRL_PWDOWN_HW 0x4000
+#define GPHY_CTRL_DEFAULT (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (\
+ GPHY_CTRL_PHY_PLL_ON |\
+ GPHY_CTRL_SEL_ANA_RST |\
+ GPHY_CTRL_HIB_PULSE |\
+ GPHY_CTRL_HIB_EN |\
+ GPHY_CTRL_PWDOWN_HW |\
+ GPHY_CTRL_PCLK_SEL_DIS |\
+ GPHY_CTRL_PHY_IDDQ)
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER 0x140E
+
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS 0x1410
+#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
+#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
+#define IDLE_STATUS_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */
+#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */
+#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */
+#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */
+#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */
+#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB is idling */
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL 0x1414
+#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */
+#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
+#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT 16
+#define MDIO_RW 0x200000 /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */
+#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
+#define MDIO_CLK_SEL_SHIFT 24
+#define MDIO_CLK_25_4 0
+#define MDIO_CLK_25_6 2
+#define MDIO_CLK_25_8 3
+#define MDIO_CLK_25_10 4
+#define MDIO_CLK_25_14 5
+#define MDIO_CLK_25_20 6
+#define MDIO_CLK_25_28 7
+#define MDIO_BUSY 0x8000000
+#define MDIO_AP_EN 0x10000000
+#define MDIO_WAIT_TIMES 10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS 0x1418
+#define PHY_STATUS_100M 0x20000
+#define PHY_STATUS_EMI_CA 0x40000
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL 0x141c
+#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure */
+#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL 0x1420
+#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure.*/
+#define BIST1_FUSE_FLAG 0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK 0x1424
+#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected . This signal comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register */
+#define REG_MAC_CTRL 0x1480
+#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */
+#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */
+#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */
+#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */
+#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */
+#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */
+#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
+#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
+#define MAC_CTRL_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */
+#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */
+#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */
+#define MAC_CTRL_PRMLEN_MASK 0xf
+#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */
+#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */
+#define MAC_CTRL_TX_PAUSE 0x10000 /* 1: transmit test pause */
+#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */
+#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */
+#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */
+#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */
+#define MAC_CTRL_SPEED_MASK 0x300000
+#define MAC_CTRL_SPEED_1000 2
+#define MAC_CTRL_SPEED_10_100 1
+#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */
+#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */
+#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */
+#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */
+#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */
+#define MAC_CTRL_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG 0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK 0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK 0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK 0x7f
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR 0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE 0x1490
+
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL 0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded */
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission */
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU 0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL 0x14a0
+#define WOL_PATTERN_EN 0x00000001
+#define WOL_PATTERN_PME_EN 0x00000002
+#define WOL_MAGIC_EN 0x00000004
+#define WOL_MAGIC_PME_EN 0x00000008
+#define WOL_LINK_CHG_EN 0x00000010
+#define WOL_LINK_CHG_PME_EN 0x00000020
+#define WOL_PATTERN_ST 0x00000100
+#define WOL_MAGIC_ST 0x00000200
+#define WOL_LINKCHG_ST 0x00000400
+#define WOL_CLK_SWITCH_EN 0x00008000
+#define WOL_PT0_EN 0x00010000
+#define WOL_PT1_EN 0x00020000
+#define WOL_PT2_EN 0x00040000
+#define WOL_PT3_EN 0x00080000
+#define WOL_PT4_EN 0x00100000
+#define WOL_PT5_EN 0x00200000
+#define WOL_PT6_EN 0x00400000
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN 0x14a4
+#define WOL_PT_LEN_MASK 0x7f
+#define WOL_PT0_LEN_SHIFT 0
+#define WOL_PT1_LEN_SHIFT 8
+#define WOL_PT2_LEN_SHIFT 16
+#define WOL_PT3_LEN_SHIFT 24
+#define WOL_PT4_LEN_SHIFT 0
+#define WOL_PT5_LEN_SHIFT 8
+#define WOL_PT6_LEN_SHIFT 16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TRD_ADDR 0x1518
+#define REG_SRAM_TRD_LEN 0x151C
+#define REG_SRAM_RXF_ADDR 0x1520
+#define REG_SRAM_RXF_LEN 0x1524
+#define REG_SRAM_TXF_ADDR 0x1528
+#define REG_SRAM_TXF_LEN 0x152C
+#define REG_SRAM_TCPH_ADDR 0x1530
+#define REG_SRAM_PKTH_ADDR 0x1532
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+
+/* Descriptor Control register */
+#define REG_RXF3_BASE_ADDR_HI 0x153C
+#define REG_DESC_BASE_ADDR_HI 0x1540
+#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */
+#define REG_HOST_RXF0_PAGE0_LO 0x1544
+#define REG_HOST_RXF0_PAGE1_LO 0x1548
+#define REG_TPD_BASE_ADDR_LO 0x154C
+#define REG_RXF1_BASE_ADDR_HI 0x1550
+#define REG_RXF2_BASE_ADDR_HI 0x1554
+#define REG_HOST_RXFPAGE_SIZE 0x1558
+#define REG_TPD_RING_SIZE 0x155C
+/* RSS about */
+#define REG_RSS_KEY0 0x14B0
+#define REG_RSS_KEY1 0x14B4
+#define REG_RSS_KEY2 0x14B8
+#define REG_RSS_KEY3 0x14BC
+#define REG_RSS_KEY4 0x14C0
+#define REG_RSS_KEY5 0x14C4
+#define REG_RSS_KEY6 0x14C8
+#define REG_RSS_KEY7 0x14CC
+#define REG_RSS_KEY8 0x14D0
+#define REG_RSS_KEY9 0x14D4
+#define REG_IDT_TABLE4 0x14E0
+#define REG_IDT_TABLE5 0x14E4
+#define REG_IDT_TABLE6 0x14E8
+#define REG_IDT_TABLE7 0x14EC
+#define REG_IDT_TABLE0 0x1560
+#define REG_IDT_TABLE1 0x1564
+#define REG_IDT_TABLE2 0x1568
+#define REG_IDT_TABLE3 0x156C
+#define REG_IDT_TABLE REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE 0x1570
+#define REG_RSS_HASH_FLAG 0x1574
+#define REG_BASE_CPU_NUMBER 0x157C
+
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL 0x1580
+#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF
+#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0
+#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */
+#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
+#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
+/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
+#define TX_TX_EARLY_TH_MASK 0x7ff
+#define TX_TX_EARLY_TH_SHIFT 0
+
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL 0x15A0
+#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */
+#define RXQ_CTRL_PBA_ALIGN_64 1
+#define RXQ_CTRL_PBA_ALIGN_128 2
+#define RXQ_CTRL_PBA_ALIGN_256 3
+#define RXQ_CTRL_Q1_EN 0x10
+#define RXQ_CTRL_Q2_EN 0x20
+#define RXQ_CTRL_Q3_EN 0x40
+#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80
+#define RXQ_CTRL_HASH_TLEN_SHIFT 8
+#define RXQ_CTRL_HASH_TLEN_MASK 0xFF
+#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000
+#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000
+#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000
+#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000
+#define RXQ_CTRL_RSS_MODE_DISABLE 0
+#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000
+#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000
+#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000
+#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000
+#define RXQ_CTRL_HASH_ENABLE 0x20000000
+#define RXQ_CTRL_CUT_THRU_EN 0x40000000
+#define RXQ_CTRL_EN 0x80000000
+
+/* Rx jumbo packet threshold and rrd retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4
+/*
+ * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
+ * When the packet length greater than or equal to this value, RXQ
+ * shall start cut-through forwarding of the received packet.
+ */
+#define RXQ_JMBOSZ_TH_MASK 0x7ff
+#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
+#define RXQ_JMBO_LKAH_MASK 0xf
+#define RXQ_JMBO_LKAH_SHIFT 11
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0
+#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16
+#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
+
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL 0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER 0x1
+#define DMA_CTRL_DMAR_ENH_ORDER 0x2
+#define DMA_CTRL_DMAR_OUT_ORDER 0x4
+#define DMA_CTRL_RCB_VALUE 0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAR_REQ_PRI 0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16
+#define DMA_CTRL_TXCMB_EN 0x100000
+#define DMA_CTRL_RXCMB_EN 0x200000
+
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER 0x15C4
+#define REG_TRIG_RRD_THRESH 0x15CA
+#define REG_TRIG_TPD_THRESH 0x15C8
+#define REG_TRIG_TXTIMER 0x15CC
+#define REG_TRIG_RXTIMER 0x15CE
+
+/* HOST RXF Page 1,2,3 address */
+#define REG_HOST_RXF1_PAGE0_LO 0x15D0
+#define REG_HOST_RXF1_PAGE1_LO 0x15D4
+#define REG_HOST_RXF2_PAGE0_LO 0x15D8
+#define REG_HOST_RXF2_PAGE1_LO 0x15DC
+#define REG_HOST_RXF3_PAGE0_LO 0x15E0
+#define REG_HOST_RXF3_PAGE1_LO 0x15E4
+
+/* Mail box */
+#define REG_MB_RXF1_RADDR 0x15B4
+#define REG_MB_RXF2_RADDR 0x15B8
+#define REG_MB_RXF3_RADDR 0x15BC
+#define REG_MB_TPD_PROD_IDX 0x15F0
+
+/* RXF-Page 0-3 PageNo & Valid bit */
+#define REG_HOST_RXF0_PAGE0_VLD 0x15F4
+#define HOST_RXF_VALID 1
+#define HOST_RXF_PAGENO_SHIFT 1
+#define HOST_RXF_PAGENO_MASK 0x7F
+#define REG_HOST_RXF0_PAGE1_VLD 0x15F5
+#define REG_HOST_RXF1_PAGE0_VLD 0x15F6
+#define REG_HOST_RXF1_PAGE1_VLD 0x15F7
+#define REG_HOST_RXF2_PAGE0_VLD 0x15F8
+#define REG_HOST_RXF2_PAGE1_VLD 0x15F9
+#define REG_HOST_RXF3_PAGE0_VLD 0x15FA
+#define REG_HOST_RXF3_PAGE1_VLD 0x15FB
+
+/* Interrupt Status Register */
+#define REG_ISR 0x1600
+#define ISR_SMB 1
+#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL 4
+#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */
+#define ISR_HOST_RXF0_OV 0x10
+#define ISR_HOST_RXF1_OV 0x20
+#define ISR_HOST_RXF2_OV 0x40
+#define ISR_HOST_RXF3_OV 0x80
+#define ISR_TXF_UN 0x100
+#define ISR_RX0_PAGE_FULL 0x200
+#define ISR_DMAR_TO_RST 0x400
+#define ISR_DMAW_TO_RST 0x800
+#define ISR_GPHY 0x1000
+#define ISR_TX_CREDIT 0x2000
+#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */
+#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */
+#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */
+#define ISR_TX_DMA 0x40000
+#define ISR_RX_PKT_1 0x80000
+#define ISR_RX_PKT_2 0x100000
+#define ISR_RX_PKT_3 0x200000
+#define ISR_MAC_RX 0x400000
+#define ISR_MAC_TX 0x800000
+#define ISR_UR_DETECTED 0x1000000
+#define ISR_FERR_DETECTED 0x2000000
+#define ISR_NFERR_DETECTED 0x4000000
+#define ISR_CERR_DETECTED 0x8000000
+#define ISR_PHY_LINKDOWN 0x10000000
+#define ISR_DIS_INT 0x80000000
+
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+
+#define IMR_NORMAL_MASK (\
+ ISR_SMB |\
+ ISR_TXF_UN |\
+ ISR_HW_RXF_OV |\
+ ISR_HOST_RXF0_OV|\
+ ISR_MANUAL |\
+ ISR_GPHY |\
+ ISR_GPHY_LPW |\
+ ISR_DMAR_TO_RST |\
+ ISR_DMAW_TO_RST |\
+ ISR_PHY_LINKDOWN|\
+ ISR_RX_PKT |\
+ ISR_TX_PKT)
+
+#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
+#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
+
+#define REG_MAC_RX_STATUS_BIN 0x1700
+#define REG_MAC_RX_STATUS_END 0x175c
+#define REG_MAC_TX_STATUS_BIN 0x1760
+#define REG_MAC_TX_STATUS_END 0x17c0
+
+/* Hardware Offset Register */
+#define REG_HOST_RXF0_PAGEOFF 0x1800
+#define REG_TPD_CONS_IDX 0x1804
+#define REG_HOST_RXF1_PAGEOFF 0x1808
+#define REG_HOST_RXF2_PAGEOFF 0x180C
+#define REG_HOST_RXF3_PAGEOFF 0x1810
+
+/* RXF-Page 0-3 Offset DMA Address */
+#define REG_HOST_RXF0_MB0_LO 0x1820
+#define REG_HOST_RXF0_MB1_LO 0x1824
+#define REG_HOST_RXF1_MB0_LO 0x1828
+#define REG_HOST_RXF1_MB1_LO 0x182C
+#define REG_HOST_RXF2_MB0_LO 0x1830
+#define REG_HOST_RXF2_MB1_LO 0x1834
+#define REG_HOST_RXF3_MB0_LO 0x1838
+#define REG_HOST_RXF3_MB1_LO 0x183C
+
+/* Tpd CMB DMA Address */
+#define REG_HOST_TX_CMB_LO 0x1840
+#define REG_HOST_SMB_ADDR_LO 0x1844
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 0x1900
+#define REG_DEBUG_DATA1 0x1904
+
+/***************************** MII definition ***************************************/
+/* PHY Common Register */
+#define MII_BMCR 0x00
+#define MII_BMSR 0x01
+#define MII_PHYSID1 0x02
+#define MII_PHYSID2 0x03
+#define MII_ADVERTISE 0x04
+#define MII_LPA 0x05
+#define MII_EXPANSION 0x06
+#define MII_AT001_CR 0x09
+#define MII_AT001_SR 0x0A
+#define MII_AT001_ESR 0x0F
+#define MII_AT001_PSCR 0x10
+#define MII_AT001_PSSR 0x11
+#define MII_INT_CTRL 0x12
+#define MII_INT_STATUS 0x13
+#define MII_SMARTSPEED 0x14
+#define MII_RERRCOUNTER 0x15
+#define MII_SREVISION 0x16
+#define MII_RESV1 0x17
+#define MII_LBRERROR 0x18
+#define MII_PHYADDR 0x19
+#define MII_RESV2 0x1a
+#define MII_TPISTATUS 0x1b
+#define MII_NCONFIG 0x1c
+
+#define MII_DBG_ADDR 0x1D
+#define MII_DBG_DATA 0x1E
+
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK 0x2040
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
+#define MII_LPA_PAUSE 0x0400 /* PAUSE */
+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
+#define MII_LPA_NPAGE 0x8000 /* Next page bit */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define MII_AR_SPEED_MASK 0x01E0
+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+/* 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+/* 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+/* 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK 0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low,
+ * 0=CLK125 toggling
+ */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+/* Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
+ * 100BASE-TX/10BASE-T:
+ * MDI Mode
+ */
+#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
+ * all speeds.
+ */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080
+/* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100
+/* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+#endif /*_ATHL1E_HW_H_*/
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
new file mode 100644
index 00000000000..35264c244cf
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -0,0 +1,2599 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "atl1e.h"
+
+#define DRV_VERSION "1.0.0.7-NAPI"
+
+char atl1e_driver_name[] = "ATL1E";
+char atl1e_driver_version[] = DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ * Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1e_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
+ /* required last entry */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl);
+
+MODULE_AUTHOR("Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD},
+ {REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD},
+ {REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD},
+ {REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD}
+};
+
+static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+ REG_RXF0_BASE_ADDR_HI,
+ REG_RXF1_BASE_ADDR_HI,
+ REG_RXF2_BASE_ADDR_HI,
+ REG_RXF3_BASE_ADDR_HI
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO},
+ {REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO},
+ {REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO},
+ {REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO}
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+ {REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO},
+ {REG_HOST_RXF1_MB0_LO, REG_HOST_RXF1_MB1_LO},
+ {REG_HOST_RXF2_MB0_LO, REG_HOST_RXF2_MB1_LO},
+ {REG_HOST_RXF3_MB0_LO, REG_HOST_RXF3_MB1_LO}
+};
+
+static const u16 atl1e_pay_load_size[] = {
+ 128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+ AT_WRITE_FLUSH(&adapter->hw);
+ }
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+ atomic_inc(&adapter->irq_sem);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+ synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+ atomic_set(&adapter->irq_sem, 0);
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+ AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1e_phy_config(unsigned long data)
+{
+ struct atl1e_adapter *adapter = (struct atl1e_adapter *) data;
+ struct atl1e_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ atl1e_restart_autoneg(hw);
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1e_reinit_locked(struct atl1e_adapter *adapter)
+{
+
+ WARN_ON(in_interrupt());
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1e_reset_task(struct work_struct *work)
+{
+ struct atl1e_adapter *adapter;
+ adapter = container_of(work, struct atl1e_adapter, reset_task);
+
+ atl1e_reinit_locked(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ int err = 0;
+ u16 speed, duplex, phy_data;
+
+ /* MII_BMSR must read twise */
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+ if ((phy_data & BMSR_LSTATUS) == 0) {
+ /* link down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ u32 value;
+ /* disable rx */
+ value = AT_READ_REG(hw, REG_MAC_CTRL);
+ value &= ~MAC_CTRL_RX_EN;
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else {
+ /* Link Up */
+ err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+ if (unlikely(err))
+ return err;
+
+ /* link result is our setting */
+ if (adapter->link_speed != speed ||
+ adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1e_setup_mac_ctrl(adapter);
+ dev_info(&pdev->dev,
+ "%s: %s NIC Link is Up<%d Mbps %s>\n",
+ atl1e_driver_name, netdev->name,
+ adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
+ "Full Duplex" : "Half Duplex");
+ }
+
+ if (!netif_carrier_ok(netdev)) {
+ /* Link down -> Up */
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+ return 0;
+}
+
+/*
+ * atl1e_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1e_link_chg_task(struct work_struct *work)
+{
+ struct atl1e_adapter *adapter;
+ unsigned long flags;
+
+ adapter = container_of(work, struct atl1e_adapter, link_chg_task);
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ atl1e_check_link(adapter);
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+static void atl1e_link_chg_event(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ u16 phy_data = 0;
+ u16 link_up = 0;
+
+ spin_lock(&adapter->mdio_lock);
+ atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ spin_unlock(&adapter->mdio_lock);
+ link_up = phy_data & BMSR_LSTATUS;
+ /* notify upper layer link down ASAP */
+ if (!link_up) {
+ if (netif_carrier_ok(netdev)) {
+ /* old link state: Up */
+ dev_info(&pdev->dev, "%s: %s NIC Link is Down\n",
+ atl1e_driver_name, netdev->name);
+ adapter->link_speed = SPEED_0;
+ netif_stop_queue(netdev);
+ }
+ }
+ schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1e_del_timer(struct atl1e_adapter *adapter)
+{
+ del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1e_cancel_work(struct atl1e_adapter *adapter)
+{
+ cancel_work_sync(&adapter->reset_task);
+ cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1e_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1e_tx_timeout(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ /* Do the reset outside of interrupt context */
+ schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1e_set_multi(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+ u32 mac_ctrl_data = 0;
+ u32 hash_value;
+
+ /* Check for Promiscuous and All Multicast modes */
+ mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL);
+
+ if (netdev->flags & IFF_PROMISC) {
+ mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+ } else if (netdev->flags & IFF_ALLMULTI) {
+ mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+ mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+ } else {
+ mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+ }
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+ /* clear the old settings from the multicast hash table */
+ AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+ AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+ /* comoute mc addresses' hash value ,and put it into hash table */
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ hash_value = atl1e_hash_mc_addr(hw, mc_ptr->dmi_addr);
+ atl1e_hash_set(hw, hash_value);
+ }
+}
+
+static void atl1e_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ u32 mac_ctrl_data = 0;
+
+ dev_dbg(&pdev->dev, "atl1e_vlan_rx_register\n");
+
+ atl1e_irq_disable(adapter);
+
+ adapter->vlgrp = grp;
+ mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
+
+ if (grp) {
+ /* enable VLAN tag insert/strip */
+ mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+ } else {
+ /* disable VLAN tag insert/strip */
+ mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+ }
+
+ AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+ atl1e_irq_enable(adapter);
+}
+
+static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ dev_dbg(&pdev->dev, "atl1e_restore_vlan !");
+ atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+/*
+ * atl1e_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+ atl1e_hw_set_mac_addr(&adapter->hw);
+
+ return 0;
+}
+
+/*
+ * atl1e_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+ if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+ return -EINVAL;
+ }
+ /* set MTU */
+ if (old_mtu != new_mtu && netif_running(netdev)) {
+ while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+ msleep(1);
+ netdev->mtu = new_mtu;
+ adapter->hw.max_frame_size = new_mtu;
+ adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3;
+ atl1e_down(adapter);
+ atl1e_up(adapter);
+ clear_bit(__AT_RESETTING, &adapter->flags);
+ }
+ return 0;
+}
+
+/*
+ * caller should hold mdio_lock
+ */
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+ return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
+ int reg_num, int val)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1e_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_mii_ioctl(struct net_device *netdev,
+ struct ifreq *ifr, int cmd)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ struct mii_ioctl_data *data = if_mii(ifr);
+ unsigned long flags;
+ int retval = 0;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&adapter->mdio_lock, flags);
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = 0;
+ break;
+
+ case SIOCGMIIREG:
+ if (!capable(CAP_NET_ADMIN)) {
+ retval = -EPERM;
+ goto out;
+ }
+ if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ &data->val_out)) {
+ retval = -EIO;
+ goto out;
+ }
+ break;
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN)) {
+ retval = -EPERM;
+ goto out;
+ }
+ if (data->reg_num & ~(0x1F)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ dev_dbg(&pdev->dev, "<atl1e_mii_ioctl> write %x %x",
+ data->reg_num, data->val_in);
+ if (atl1e_write_phy_reg(&adapter->hw,
+ data->reg_num, data->val_in)) {
+ retval = -EIO;
+ goto out;
+ }
+ break;
+
+ default:
+ retval = -EOPNOTSUPP;
+ break;
+ }
+out:
+ spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+ return retval;
+
+}
+
+/*
+ * atl1e_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ return atl1e_mii_ioctl(netdev, ifr, cmd);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void atl1e_setup_pcicmd(struct pci_dev *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO);
+ cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+ /*
+ * some motherboards BIOS(PXE/EFI) driver may set PME
+ * while they transfer control to OS (Windows/Linux)
+ * so we should clear this bit before NIC work normally
+ */
+ pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+ msleep(1);
+}
+
+/*
+ * atl1e_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+{
+ return 0;
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 phy_status_data = 0;
+
+ adapter->wol = 0;
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+ adapter->num_rx_queues = 1;
+
+ /* PCI config space info */
+ hw->vendor_id = pdev->vendor;
+ hw->device_id = pdev->device;
+ hw->subsystem_vendor_id = pdev->subsystem_vendor;
+ hw->subsystem_id = pdev->subsystem_device;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+ /* nic type */
+ if (hw->revision_id >= 0xF0) {
+ hw->nic_type = athr_l2e_revB;
+ } else {
+ if (phy_status_data & PHY_STATUS_100M)
+ hw->nic_type = athr_l1e;
+ else
+ hw->nic_type = athr_l2e_revA;
+ }
+
+ phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+ if (phy_status_data & PHY_STATUS_EMI_CA)
+ hw->emi_ca = true;
+ else
+ hw->emi_ca = false;
+
+ hw->phy_configured = false;
+ hw->preamble_len = 7;
+ hw->max_frame_size = adapter->netdev->mtu;
+ hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN + 7) >> 3;
+
+ hw->rrs_type = atl1e_rrs_disable;
+ hw->indirect_tab = 0;
+ hw->base_cpu = 0;
+
+ /* need confirm */
+
+ hw->ict = 50000; /* 100ms */
+ hw->smb_timer = 200000; /* 200ms */
+ hw->tpd_burst = 5;
+ hw->rrd_thresh = 1;
+ hw->tpd_thresh = adapter->tx_ring.count / 2;
+ hw->rx_count_down = 4; /* 2us resolution */
+ hw->tx_count_down = hw->imt * 4 / 3;
+ hw->dmar_block = atl1e_dma_req_1024;
+ hw->dmaw_block = atl1e_dma_req_1024;
+ hw->dmar_dly_cnt = 15;
+ hw->dmaw_dly_cnt = 4;
+
+ if (atl1e_alloc_queues(adapter)) {
+ dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+ return -ENOMEM;
+ }
+
+ atomic_set(&adapter->irq_sem, 1);
+ spin_lock_init(&adapter->mdio_lock);
+ spin_lock_init(&adapter->tx_lock);
+
+ set_bit(__AT_DOWN, &adapter->flags);
+
+ return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ struct pci_dev *pdev = adapter->pdev;
+ u16 index, ring_count;
+
+ if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+ return;
+
+ ring_count = tx_ring->count;
+ /* first unmmap dma */
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->dma) {
+ pci_unmap_page(pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ tx_buffer->dma = 0;
+ }
+ }
+ /* second free skb */
+ for (index = 0; index < ring_count; index++) {
+ tx_buffer = &tx_ring->tx_buffer[index];
+ if (tx_buffer->skb) {
+ dev_kfree_skb_any(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+ }
+ }
+ /* Zero out Tx-buffers */
+ memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+ ring_count);
+ memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+ ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc;
+ u16 i, j;
+
+
+ if (adapter->ring_vir_addr == NULL)
+ return;
+ /* Zero out the descriptor ring */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ if (rx_page_desc[i].rx_page[j].addr != NULL) {
+ memset(rx_page_desc[i].rx_page[j].addr, 0,
+ rx_ring->real_page_size);
+ }
+ }
+ }
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+ *ring_size = ((u32)(adapter->tx_ring.count *
+ sizeof(struct atl1e_tpd_desc) + 7
+ /* tx ring, qword align */
+ + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE *
+ adapter->num_rx_queues + 31
+ /* rx ring, 32 bytes align */
+ + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) *
+ sizeof(u32) + 3));
+ /* tx, rx cmd, dword align */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ rx_ring->real_page_size = adapter->rx_ring.page_size
+ + adapter->hw.max_frame_size
+ + ETH_HLEN + VLAN_HLEN
+ + ETH_FCS_LEN;
+ rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32);
+ atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+ adapter->ring_vir_addr = NULL;
+ adapter->rx_ring.desc = NULL;
+ rwlock_init(&adapter->tx_ring.tx_lock);
+
+ return;
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = NULL;
+ struct atl1e_rx_ring *rx_ring = NULL;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int i, j;
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+ rx_page_desc = rx_ring->rx_page_desc;
+
+ tx_ring->next_to_use = 0;
+ atomic_set(&tx_ring->next_to_clean, 0);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ rx_page_desc[i].rx_using = 0;
+ rx_page_desc[i].rx_nxseq = 0;
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ *rx_page_desc[i].rx_page[j].write_offset_addr = 0;
+ rx_page_desc[i].rx_page[j].read_offset = 0;
+ }
+ }
+}
+
+/*
+ * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+
+ if (adapter->ring_vir_addr) {
+ pci_free_consistent(pdev, adapter->ring_size,
+ adapter->ring_vir_addr, adapter->ring_dma);
+ adapter->ring_vir_addr = NULL;
+ }
+
+ if (adapter->tx_ring.tx_buffer) {
+ kfree(adapter->tx_ring.tx_buffer);
+ adapter->tx_ring.tx_buffer = NULL;
+ }
+}
+
+/*
+ * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1e_tx_ring *tx_ring;
+ struct atl1e_rx_ring *rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc;
+ int size, i, j;
+ u32 offset = 0;
+ int err = 0;
+
+ if (adapter->ring_vir_addr != NULL)
+ return 0; /* alloced already */
+
+ tx_ring = &adapter->tx_ring;
+ rx_ring = &adapter->rx_ring;
+
+ /* real ring DMA buffer */
+
+ size = adapter->ring_size;
+ adapter->ring_vir_addr = pci_alloc_consistent(pdev,
+ adapter->ring_size, &adapter->ring_dma);
+
+ if (adapter->ring_vir_addr == NULL) {
+ dev_err(&pdev->dev, "pci_alloc_consistent failed, "
+ "size = D%d", size);
+ return -ENOMEM;
+ }
+
+ memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+ rx_page_desc = rx_ring->rx_page_desc;
+
+ /* Init TPD Ring */
+ tx_ring->dma = roundup(adapter->ring_dma, 8);
+ offset = tx_ring->dma - adapter->ring_dma;
+ tx_ring->desc = (struct atl1e_tpd_desc *)
+ (adapter->ring_vir_addr + offset);
+ size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
+ tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
+ if (tx_ring->tx_buffer == NULL) {
+ dev_err(&pdev->dev, "kzalloc failed , size = D%d", size);
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ /* Init RXF-Pages */
+ offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
+ offset = roundup(offset, 32);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc[i].rx_page[j].dma =
+ adapter->ring_dma + offset;
+ rx_page_desc[i].rx_page[j].addr =
+ adapter->ring_vir_addr + offset;
+ offset += rx_ring->real_page_size;
+ }
+ }
+
+ /* Init CMB dma address */
+ tx_ring->cmb_dma = adapter->ring_dma + offset;
+ tx_ring->cmb = (u32 *)(adapter->ring_vir_addr + offset);
+ offset += sizeof(u32);
+
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ rx_page_desc[i].rx_page[j].write_offset_dma =
+ adapter->ring_dma + offset;
+ rx_page_desc[i].rx_page[j].write_offset_addr =
+ adapter->ring_vir_addr + offset;
+ offset += sizeof(u32);
+ }
+ }
+
+ if (unlikely(offset > adapter->ring_size)) {
+ dev_err(&pdev->dev, "offset(%d) > ring size(%d) !!\n",
+ offset, adapter->ring_size);
+ err = -1;
+ goto failed;
+ }
+
+ return 0;
+failed:
+ if (adapter->ring_vir_addr != NULL) {
+ pci_free_consistent(pdev, adapter->ring_size,
+ adapter->ring_vir_addr, adapter->ring_dma);
+ adapter->ring_vir_addr = NULL;
+ }
+ return err;
+}
+
+static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
+{
+
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ struct atl1e_rx_ring *rx_ring =
+ (struct atl1e_rx_ring *)&adapter->rx_ring;
+ struct atl1e_tx_ring *tx_ring =
+ (struct atl1e_tx_ring *)&adapter->tx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc = NULL;
+ int i, j;
+
+ AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
+ (u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32));
+ AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO,
+ (u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK));
+ AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
+ AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO,
+ (u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK));
+
+ rx_page_desc = rx_ring->rx_page_desc;
+ /* RXF Page Physical address / Page Length */
+ for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) {
+ AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i],
+ (u32)((adapter->ring_dma &
+ AT_DMA_HI_ADDR_MASK) >> 32));
+ for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+ u32 page_phy_addr;
+ u32 offset_phy_addr;
+
+ page_phy_addr = rx_page_desc[i].rx_page[j].dma;
+ offset_phy_addr =
+ rx_page_desc[i].rx_page[j].write_offset_dma;
+
+ AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j],
+ page_phy_addr & AT_DMA_LO_ADDR_MASK);
+ AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j],
+ offset_phy_addr & AT_DMA_LO_ADDR_MASK);
+ AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1);
+ }
+ }
+ /* Page Length */
+ AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
+ /* Load all of base address above */
+ AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+
+ return;
+}
+
+static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 dev_ctrl_data = 0;
+ u32 max_pay_load = 0;
+ u32 jumbo_thresh = 0;
+ u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
+
+ /* configure TXQ param */
+ if (hw->nic_type != athr_l2e_revB) {
+ extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ if (hw->max_frame_size <= 1500) {
+ jumbo_thresh = hw->max_frame_size + extra_size;
+ } else if (hw->max_frame_size < 6*1024) {
+ jumbo_thresh =
+ (hw->max_frame_size + extra_size) * 2 / 3;
+ } else {
+ jumbo_thresh = (hw->max_frame_size + extra_size) / 2;
+ }
+ AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
+ }
+
+ dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
+ DEVICE_CTRL_MAX_PAYLOAD_MASK;
+
+ hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+
+ max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
+ DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+ hw->dmar_block = min(max_pay_load, hw->dmar_block);
+
+ if (hw->nic_type != athr_l2e_revB)
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
+ atl1e_pay_load_size[hw->dmar_block]);
+ /* enable TXQ */
+ AT_WRITE_REGW(hw, REG_TXQ_CTRL,
+ (((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK)
+ << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
+ | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
+ return;
+}
+
+static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+ u32 rxf_len = 0;
+ u32 rxf_low = 0;
+ u32 rxf_high = 0;
+ u32 rxf_thresh_data = 0;
+ u32 rxq_ctrl_data = 0;
+
+ if (hw->nic_type != athr_l2e_revB) {
+ AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
+ (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) <<
+ RXQ_JMBOSZ_TH_SHIFT |
+ (1 & RXQ_JMBO_LKAH_MASK) <<
+ RXQ_JMBO_LKAH_SHIFT));
+
+ rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+ rxf_high = rxf_len * 4 / 5;
+ rxf_low = rxf_len / 5;
+ rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK)
+ << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
+ << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+
+ AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
+ }
+
+ /* RRS */
+ AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+ AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+
+ if (hw->rrs_type & atl1e_rrs_ipv4)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4;
+
+ if (hw->rrs_type & atl1e_rrs_ipv4_tcp)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP;
+
+ if (hw->rrs_type & atl1e_rrs_ipv6)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6;
+
+ if (hw->rrs_type & atl1e_rrs_ipv6_tcp)
+ rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP;
+
+ if (hw->rrs_type != atl1e_rrs_disable)
+ rxq_ctrl_data |=
+ (RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT);
+
+ rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 |
+ RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+
+ AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+ return;
+}
+
+static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 dma_ctrl_data = 0;
+
+ dma_ctrl_data = DMA_CTRL_RXCMB_EN;
+ dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+ << DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+ dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
+ dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+ << DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+ dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+ << DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+ AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+ return;
+}
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
+{
+ u32 value;
+ struct atl1e_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN |
+ MAC_CTRL_RX_EN ;
+
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+
+ value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ value |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+
+ if (adapter->vlgrp)
+ value |= MAC_CTRL_RMV_VLAN;
+
+ value |= MAC_CTRL_BC_EN;
+ if (netdev->flags & IFF_PROMISC)
+ value |= MAC_CTRL_PROMIS_EN;
+ if (netdev->flags & IFF_ALLMULTI)
+ value |= MAC_CTRL_MC_ALL_EN;
+
+ AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+/*
+ * atl1e_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1e_configure(struct atl1e_adapter *adapter)
+{
+ struct atl1e_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
+
+ u32 intr_status_data = 0;
+
+ /* clear interrupt status */
+ AT_WRITE_REG(hw, REG_ISR, ~0);
+
+ /* 1. set MAC Address */
+ atl1e_hw_set_mac_addr(hw);
+
+ /* 2. Init the Multicast HASH table done by set_muti */
+
+ /* 3. Clear any WOL status */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
+ * TPD Ring/SMB/RXF0 Page CMBs, they use the same
+ * High 32bits memory */
+ atl1e_configure_des_ring(adapter);
+
+ /* 5. set Interrupt Moderator Timer */
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt);
+ AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt);
+ AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
+ MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
+
+ /* 6. rx/tx threshold to trig interrupt */
+ AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh);
+ AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh);
+ AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down);
+ AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down);
+
+ /* 7. set Interrupt Clear Timer */
+ AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict);
+
+ /* 8. set MTU */
+ AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+ VLAN_HLEN + ETH_FCS_LEN);
+
+ /* 9. config TXQ early tx threshold */
+ atl1e_configure_tx(adapter);
+
+ /* 10. config RXQ */
+ atl1e_configure_rx(adapter);
+
+ /* 11. config DMA Engine */
+ atl1e_configure_dma(adapter);
+
+ /* 12. smb timer to trig interrupt */
+ AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer);
+
+ intr_status_data = AT_READ_REG(hw, REG_ISR);
+ if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) {
+ dev_err(&pdev->dev, "atl1e_configure failed,"
+ "PCIE phy link down\n");
+ return -1;
+ }
+
+ AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
+ return 0;
+}
+
+/*
+ * atl1e_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1e_get_stats(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw_stats *hw_stats = &adapter->hw_stats;
+ struct net_device_stats *net_stats = &adapter->net_stats;
+
+ net_stats->rx_packets = hw_stats->rx_ok;
+ net_stats->tx_packets = hw_stats->tx_ok;
+ net_stats->rx_bytes = hw_stats->rx_byte_cnt;
+ net_stats->tx_bytes = hw_stats->tx_byte_cnt;
+ net_stats->multicast = hw_stats->rx_mcast;
+ net_stats->collisions = hw_stats->tx_1_col +
+ hw_stats->tx_2_col * 2 +
+ hw_stats->tx_late_col + hw_stats->tx_abort_col;
+
+ net_stats->rx_errors = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+ hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+ hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+ net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov;
+ net_stats->rx_length_errors = hw_stats->rx_len_err;
+ net_stats->rx_crc_errors = hw_stats->rx_fcs_err;
+ net_stats->rx_frame_errors = hw_stats->rx_align_err;
+ net_stats->rx_over_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+ net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+ net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+ hw_stats->tx_underrun + hw_stats->tx_trunc;
+ net_stats->tx_fifo_errors = hw_stats->tx_underrun;
+ net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+ net_stats->tx_window_errors = hw_stats->tx_late_col;
+
+ return &adapter->net_stats;
+}
+
+static void atl1e_update_hw_stats(struct atl1e_adapter *adapter)
+{
+ u16 hw_reg_addr = 0;
+ unsigned long *stats_item = NULL;
+
+ /* update rx status */
+ hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+ stats_item = &adapter->hw_stats.rx_ok;
+ while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+ *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+ stats_item++;
+ hw_reg_addr += 4;
+ }
+ /* update tx status */
+ hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+ stats_item = &adapter->hw_stats.tx_ok;
+ while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+ *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+ stats_item++;
+ hw_reg_addr += 4;
+ }
+}
+
+static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
+{
+ u16 phy_data;
+
+ spin_lock(&adapter->mdio_lock);
+ atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
+ spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+ &adapter->tx_ring;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
+ u16 next_to_clean = atomic_read(&tx_ring->next_to_clean);
+
+ while (next_to_clean != hw_next_to_clean) {
+ tx_buffer = &tx_ring->tx_buffer[next_to_clean];
+ if (tx_buffer->dma) {
+ pci_unmap_page(adapter->pdev, tx_buffer->dma,
+ tx_buffer->length, PCI_DMA_TODEVICE);
+ tx_buffer->dma = 0;
+ }
+
+ if (tx_buffer->skb) {
+ dev_kfree_skb_irq(tx_buffer->skb);
+ tx_buffer->skb = NULL;
+ }
+
+ if (++next_to_clean == tx_ring->count)
+ next_to_clean = 0;
+ }
+
+ atomic_set(&tx_ring->next_to_clean, next_to_clean);
+
+ if (netif_queue_stopped(adapter->netdev) &&
+ netif_carrier_ok(adapter->netdev)) {
+ netif_wake_queue(adapter->netdev);
+ }
+
+ return true;
+}
+
+/*
+ * atl1e_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1e_intr(int irq, void *data)
+{
+ struct net_device *netdev = data;
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1e_hw *hw = &adapter->hw;
+ int max_ints = AT_MAX_INT_WORK;
+ int handled = IRQ_NONE;
+ u32 status;
+
+ do {
+ status = AT_READ_REG(hw, REG_ISR);
+ if ((status & IMR_NORMAL_MASK) == 0 ||
+ (status & ISR_DIS_INT) != 0) {
+ if (max_ints != AT_MAX_INT_WORK)
+ handled = IRQ_HANDLED;
+ break;
+ }
+ /* link event */
+ if (status & ISR_GPHY)
+ atl1e_clear_phy_int(adapter);
+ /* Ack ISR */
+ AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+ handled = IRQ_HANDLED;
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ dev_err(&pdev->dev,
+ "pcie phy linkdown %x\n", status);
+ if (netif_running(adapter->netdev)) {
+ /* reset MAC */
+ atl1e_irq_reset(adapter);
+ schedule_work(&adapter->reset_task);
+ break;
+ }
+ }
+
+ /* check if DMA read/write error */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ dev_err(&pdev->dev,
+ "PCIE DMA RW error (status = 0x%x)\n",
+ status);
+ atl1e_irq_reset(adapter);
+ schedule_work(&adapter->reset_task);
+ break;
+ }
+
+ if (status & ISR_SMB)
+ atl1e_update_hw_stats(adapter);
+
+ /* link event */
+ if (status & (ISR_GPHY | ISR_MANUAL)) {
+ adapter->net_stats.tx_carrier_errors++;
+ atl1e_link_chg_event(adapter);
+ break;
+ }
+
+ /* transmit event */
+ if (status & ISR_TX_EVENT)
+ atl1e_clean_tx_irq(adapter);
+
+ if (status & ISR_RX_EVENT) {
+ /*
+ * disable rx interrupts, without
+ * the synchronize_irq bit
+ */
+ AT_WRITE_REG(hw, REG_IMR,
+ IMR_NORMAL_MASK & ~ISR_RX_EVENT);
+ AT_WRITE_FLUSH(hw);
+ if (likely(netif_rx_schedule_prep(netdev,
+ &adapter->napi)))
+ __netif_rx_schedule(netdev, &adapter->napi);
+ }
+ } while (--max_ints > 0);
+ /* re-enable Interrupt*/
+ AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+
+ return handled;
+}
+
+static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_recv_ret_status *prrs)
+{
+ u8 *packet = (u8 *)(prrs + 1);
+ struct iphdr *iph;
+ u16 head_len = ETH_HLEN;
+ u16 pkt_flags;
+ u16 err_flags;
+
+ skb->ip_summed = CHECKSUM_NONE;
+ pkt_flags = prrs->pkt_flag;
+ err_flags = prrs->err_flag;
+ if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
+ ((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) {
+ if (pkt_flags & RRS_IS_IPV4) {
+ if (pkt_flags & RRS_IS_802_3)
+ head_len += 8;
+ iph = (struct iphdr *) (packet + head_len);
+ if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF))
+ goto hw_xsum;
+ }
+ if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ return;
+ }
+ }
+
+hw_xsum :
+ return;
+}
+
+static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter,
+ u8 que)
+{
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc;
+ u8 rx_using = rx_page_desc[que].rx_using;
+
+ return (struct atl1e_rx_page *)&(rx_page_desc[que].rx_page[rx_using]);
+}
+
+static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
+ int *work_done, int work_to_do)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
+ &adapter->rx_ring;
+ struct atl1e_rx_page_desc *rx_page_desc =
+ (struct atl1e_rx_page_desc *) rx_ring->rx_page_desc;
+ struct sk_buff *skb = NULL;
+ struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que);
+ u32 packet_size, write_offset;
+ struct atl1e_recv_ret_status *prrs;
+
+ write_offset = *(rx_page->write_offset_addr);
+ if (likely(rx_page->read_offset < write_offset)) {
+ do {
+ if (*work_done >= work_to_do)
+ break;
+ (*work_done)++;
+ /* get new packet's rrs */
+ prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
+ rx_page->read_offset);
+ /* check sequence number */
+ if (prrs->seq_num != rx_page_desc[que].rx_nxseq) {
+ dev_err(&pdev->dev,
+ "rx sequence number"
+ " error (rx=%d) (expect=%d)\n",
+ prrs->seq_num,
+ rx_page_desc[que].rx_nxseq);
+ rx_page_desc[que].rx_nxseq++;
+ /* just for debug use */
+ AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0,
+ (((u32)prrs->seq_num) << 16) |
+ rx_page_desc[que].rx_nxseq);
+ goto fatal_err;
+ }
+ rx_page_desc[que].rx_nxseq++;
+
+ /* error packet */
+ if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
+ if (prrs->err_flag & (RRS_ERR_BAD_CRC |
+ RRS_ERR_DRIBBLE | RRS_ERR_CODE |
+ RRS_ERR_TRUNC)) {
+ /* hardware error, discard this packet*/
+ dev_err(&pdev->dev,
+ "rx packet desc error %x\n",
+ *((u32 *)prrs + 1));
+ goto skip_pkt;
+ }
+ }
+
+ packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) - 4; /* CRC */
+ skb = netdev_alloc_skb(netdev,
+ packet_size + NET_IP_ALIGN);
+ if (skb == NULL) {
+ dev_warn(&pdev->dev, "%s: Memory squeeze,"
+ "deferring packet.\n", netdev->name);
+ goto skip_pkt;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb->dev = netdev;
+ memcpy(skb->data, (u8 *)(prrs + 1), packet_size);
+ skb_put(skb, packet_size);
+ skb->protocol = eth_type_trans(skb, netdev);
+ atl1e_rx_checksum(adapter, skb, prrs);
+
+ if (unlikely(adapter->vlgrp &&
+ (prrs->pkt_flag & RRS_IS_VLAN_TAG))) {
+ u16 vlan_tag = (prrs->vtag >> 4) |
+ ((prrs->vtag & 7) << 13) |
+ ((prrs->vtag & 8) << 9);
+ dev_dbg(&pdev->dev,
+ "RXD VLAN TAG<RRD>=0x%04x\n",
+ prrs->vtag);
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ vlan_tag);
+ } else {
+ netif_receive_skb(skb);
+ }
+
+ netdev->last_rx = jiffies;
+skip_pkt:
+ /* skip current packet whether it's ok or not. */
+ rx_page->read_offset +=
+ (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+ RRS_PKT_SIZE_MASK) +
+ sizeof(struct atl1e_recv_ret_status) + 31) &
+ 0xFFFFFFE0);
+
+ if (rx_page->read_offset >= rx_ring->page_size) {
+ /* mark this page clean */
+ u16 reg_addr;
+ u8 rx_using;
+
+ rx_page->read_offset =
+ *(rx_page->write_offset_addr) = 0;
+ rx_using = rx_page_desc[que].rx_using;
+ reg_addr =
+ atl1e_rx_page_vld_regs[que][rx_using];
+ AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
+ rx_page_desc[que].rx_using ^= 1;
+ rx_page = atl1e_get_rx_page(adapter, que);
+ }
+ write_offset = *(rx_page->write_offset_addr);
+ } while (rx_page->read_offset < write_offset);
+ }
+
+ return;
+
+fatal_err:
+ if (!test_bit(__AT_DOWN, &adapter->flags))
+ schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1e_clean(struct napi_struct *napi, int budget)
+{
+ struct atl1e_adapter *adapter =
+ container_of(napi, struct atl1e_adapter, napi);
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ u32 imr_data;
+ int work_done = 0;
+
+ /* Keep link state information with original netdev */
+ if (!netif_carrier_ok(adapter->netdev))
+ goto quit_polling;
+
+ atl1e_clean_rx_irq(adapter, 0, &work_done, budget);
+
+ /* If no Tx and not enough Rx work done, exit the polling mode */
+ if (work_done < budget) {
+quit_polling:
+ netif_rx_complete(netdev, napi);
+ imr_data = AT_READ_REG(&adapter->hw, REG_IMR);
+ AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT);
+ /* test debug */
+ if (test_bit(__AT_DOWN, &adapter->flags)) {
+ atomic_dec(&adapter->irq_sem);
+ dev_err(&pdev->dev,
+ "atl1e_clean is called when AT_DOWN\n");
+ }
+ /* reenable RX intr */
+ /*atl1e_irq_enable(adapter); */
+
+ }
+ return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void atl1e_netpoll(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ disable_irq(adapter->pdev->irq);
+ atl1e_intr(adapter->pdev->irq, netdev);
+ enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+ u16 next_to_clean = 0;
+
+ next_to_clean = atomic_read(&tx_ring->next_to_clean);
+ next_to_use = tx_ring->next_to_use;
+
+ return (u16)(next_to_clean > next_to_use) ?
+ (next_to_clean - next_to_use - 1) :
+ (tx_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1e_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ u16 next_to_use = 0;
+
+ next_to_use = tx_ring->next_to_use;
+ if (++tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+
+ memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
+ return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
+}
+
+static struct atl1e_tx_buffer *
+atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+
+ return &tx_ring->tx_buffer[tpd - tx_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)
+{
+ int i = 0;
+ u16 tpd_req = 1;
+ u16 fg_size = 0;
+ u16 proto_hdr_len = 0;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ fg_size = skb_shinfo(skb)->frags[i].size;
+ tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT);
+ }
+
+ if (skb_is_gso(skb)) {
+ if (skb->protocol == ntohs(ETH_P_IP) ||
+ (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) {
+ proto_hdr_len = skb_transport_offset(skb) +
+ tcp_hdrlen(skb);
+ if (proto_hdr_len < skb_headlen(skb)) {
+ tpd_req += ((skb_headlen(skb) - proto_hdr_len +
+ MAX_TX_BUF_LEN - 1) >>
+ MAX_TX_BUF_SHIFT);
+ }
+ }
+
+ }
+ return tpd_req;
+}
+
+static int atl1e_tso_csum(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ u8 hdr_len;
+ u32 real_len;
+ unsigned short offload_type;
+ int err;
+
+ if (skb_is_gso(skb)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return -1;
+ }
+ offload_type = skb_shinfo(skb)->gso_type;
+
+ if (offload_type & SKB_GSO_TCPV4) {
+ real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+ + ntohs(ip_hdr(skb)->tot_len));
+
+ if (real_len < skb->len)
+ pskb_trim(skb, real_len);
+
+ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (unlikely(skb->len == hdr_len)) {
+ /* only xsum need */
+ dev_warn(&pdev->dev,
+ "IPV4 tso with zero data??\n");
+ goto check_sum;
+ } else {
+ ip_hdr(skb)->check = 0;
+ ip_hdr(skb)->tot_len = 0;
+ tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+ ip_hdr(skb)->saddr,
+ ip_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ tpd->word3 |= (ip_hdr(skb)->ihl &
+ TDP_V4_IPHL_MASK) <<
+ TPD_V4_IPHL_SHIFT;
+ tpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+ TPD_TCPHDRLEN_MASK) <<
+ TPD_TCPHDRLEN_SHIFT;
+ tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+ TPD_MSS_MASK) << TPD_MSS_SHIFT;
+ tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+ }
+ return 0;
+ }
+
+ if (offload_type & SKB_GSO_TCPV6) {
+ real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data)
+ + ntohs(ipv6_hdr(skb)->payload_len));
+ if (real_len < skb->len)
+ pskb_trim(skb, real_len);
+
+ /* check payload == 0 byte ? */
+ hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (unlikely(skb->len == hdr_len)) {
+ /* only xsum need */
+ dev_warn(&pdev->dev,
+ "IPV6 tso with zero data??\n");
+ goto check_sum;
+ } else {
+ tcp_hdr(skb)->check = ~csum_ipv6_magic(
+ &ipv6_hdr(skb)->saddr,
+ &ipv6_hdr(skb)->daddr,
+ 0, IPPROTO_TCP, 0);
+ tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT;
+ hdr_len >>= 1;
+ tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) <<
+ TPD_V6_IPHLLO_SHIFT;
+ tpd->word3 |= ((hdr_len >> 3) &
+ TPD_V6_IPHLHI_MASK) <<
+ TPD_V6_IPHLHI_SHIFT;
+ tpd->word3 |= (tcp_hdrlen(skb) >> 2 &
+ TPD_TCPHDRLEN_MASK) <<
+ TPD_TCPHDRLEN_SHIFT;
+ tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+ TPD_MSS_MASK) << TPD_MSS_SHIFT;
+ tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+ }
+ }
+ return 0;
+ }
+
+check_sum:
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ u8 css, cso;
+
+ cso = skb_transport_offset(skb);
+ if (unlikely(cso & 0x1)) {
+ dev_err(&adapter->pdev->dev,
+ "pay load offset should not ant event number\n");
+ return -1;
+ } else {
+ css = cso + skb->csum_offset;
+ tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) <<
+ TPD_PLOADOFFSET_SHIFT;
+ tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) <<
+ TPD_CCSUMOFFSET_SHIFT;
+ tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT;
+ }
+ }
+
+ return 0;
+}
+
+static void atl1e_tx_map(struct atl1e_adapter *adapter,
+ struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tpd_desc *use_tpd = NULL;
+ struct atl1e_tx_buffer *tx_buffer = NULL;
+ u16 buf_len = skb->len - skb->data_len;
+ u16 map_len = 0;
+ u16 mapped_len = 0;
+ u16 hdr_len = 0;
+ u16 nr_frags;
+ u16 f;
+ int segment;
+
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
+ if (segment) {
+ /* TSO */
+ map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+ use_tpd = tpd;
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ tx_buffer->length = map_len;
+ tx_buffer->dma = pci_map_single(adapter->pdev,
+ skb->data, hdr_len, PCI_DMA_TODEVICE);
+ mapped_len += map_len;
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+
+ while (mapped_len < buf_len) {
+ /* mapped_len == 0, means we should use the first tpd,
+ which is given by caller */
+ if (mapped_len == 0) {
+ use_tpd = tpd;
+ } else {
+ use_tpd = atl1e_get_tpd(adapter);
+ memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+ }
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ tx_buffer->skb = NULL;
+
+ tx_buffer->length = map_len =
+ ((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ?
+ MAX_TX_BUF_LEN : (buf_len - mapped_len);
+ tx_buffer->dma =
+ pci_map_single(adapter->pdev, skb->data + mapped_len,
+ map_len, PCI_DMA_TODEVICE);
+ mapped_len += map_len;
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+
+ for (f = 0; f < nr_frags; f++) {
+ struct skb_frag_struct *frag;
+ u16 i;
+ u16 seg_num;
+
+ frag = &skb_shinfo(skb)->frags[f];
+ buf_len = frag->size;
+
+ seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ for (i = 0; i < seg_num; i++) {
+ use_tpd = atl1e_get_tpd(adapter);
+ memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+
+ tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+ if (tx_buffer->skb)
+ BUG();
+
+ tx_buffer->skb = NULL;
+ tx_buffer->length =
+ (buf_len > MAX_TX_BUF_LEN) ?
+ MAX_TX_BUF_LEN : buf_len;
+ buf_len -= tx_buffer->length;
+
+ tx_buffer->dma =
+ pci_map_page(adapter->pdev, frag->page,
+ frag->page_offset +
+ (i * MAX_TX_BUF_LEN),
+ tx_buffer->length,
+ PCI_DMA_TODEVICE);
+ use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+ use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+ ((cpu_to_le32(tx_buffer->length) &
+ TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+ }
+ }
+
+ if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK)
+ /* note this one is a tcp header */
+ tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
+ /* The last tpd */
+
+ use_tpd->word3 |= 1 << TPD_EOP_SHIFT;
+ /* The last buffer info contain the skb address,
+ so it will be free after unmap */
+ tx_buffer->skb = skb;
+}
+
+static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
+ struct atl1e_tpd_desc *tpd)
+{
+ struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
+}
+
+static int atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ u16 tpd_req = 1;
+ struct atl1e_tpd_desc *tpd;
+
+ if (test_bit(__AT_DOWN, &adapter->flags)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (unlikely(skb->len <= 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ tpd_req = atl1e_cal_tdp_req(skb);
+ if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
+ return NETDEV_TX_LOCKED;
+
+ if (atl1e_tpd_avail(adapter) < tpd_req) {
+ /* no enough descriptor, just stop queue */
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ tpd = atl1e_get_tpd(adapter);
+
+ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ u16 vlan_tag = vlan_tx_tag_get(skb);
+ u16 atl1e_vlan_tag;
+
+ tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
+ AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag);
+ tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) <<
+ TPD_VLAN_SHIFT;
+ }
+
+ if (skb->protocol == ntohs(ETH_P_8021Q))
+ tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT;
+
+ if (skb_network_offset(skb) != ETH_HLEN)
+ tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */
+
+ /* do TSO and check sum */
+ if (atl1e_tso_csum(adapter, skb, tpd) != 0) {
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ atl1e_tx_map(adapter, skb, tpd);
+ atl1e_tx_queue(adapter, tpd_req, tpd);
+
+ netdev->trans_start = jiffies;
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
+ return NETDEV_TX_OK;
+}
+
+static void atl1e_free_irq(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ free_irq(adapter->pdev->irq, netdev);
+
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+}
+
+static int atl1e_request_irq(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct net_device *netdev = adapter->netdev;
+ int flags = 0;
+ int err = 0;
+
+ adapter->have_msi = true;
+ err = pci_enable_msi(adapter->pdev);
+ if (err) {
+ dev_dbg(&pdev->dev,
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = false;
+ } else
+ netdev->irq = pdev->irq;
+
+
+ if (!adapter->have_msi)
+ flags |= IRQF_SHARED;
+ err = request_irq(adapter->pdev->irq, &atl1e_intr, flags,
+ netdev->name, netdev);
+ if (err) {
+ dev_dbg(&pdev->dev,
+ "Unable to allocate interrupt Error: %d\n", err);
+ if (adapter->have_msi)
+ pci_disable_msi(adapter->pdev);
+ return err;
+ }
+ dev_dbg(&pdev->dev, "atl1e_request_irq OK\n");
+ return err;
+}
+
+int atl1e_up(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+ u32 val;
+
+ /* hardware has been reset, we need to reload some things */
+ err = atl1e_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ return err;
+ }
+ atl1e_init_ring_ptrs(adapter);
+ atl1e_set_multi(netdev);
+ atl1e_restore_vlan(adapter);
+
+ if (atl1e_configure(adapter)) {
+ err = -EIO;
+ goto err_up;
+ }
+
+ clear_bit(__AT_DOWN, &adapter->flags);
+ napi_enable(&adapter->napi);
+ atl1e_irq_enable(adapter);
+ val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+ AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+ val | MASTER_CTRL_MANUAL_INT);
+
+err_up:
+ return err;
+}
+
+void atl1e_down(struct atl1e_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* signal that we're down so the interrupt handler does not
+ * reschedule our watchdog timer */
+ set_bit(__AT_DOWN, &adapter->flags);
+
+#ifdef NETIF_F_LLTX
+ netif_stop_queue(netdev);
+#else
+ netif_tx_disable(netdev);
+#endif
+
+ /* reset MAC to disable all RX/TX */
+ atl1e_reset_hw(&adapter->hw);
+ msleep(1);
+
+ napi_disable(&adapter->napi);
+ atl1e_del_timer(adapter);
+ atl1e_irq_disable(adapter);
+
+ netif_carrier_off(netdev);
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+ atl1e_clean_tx_ring(adapter);
+ atl1e_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1e_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1e_open(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ /* disallow open during test */
+ if (test_bit(__AT_TESTING, &adapter->flags))
+ return -EBUSY;
+
+ /* allocate rx/tx dma buffer & descriptors */
+ atl1e_init_ring_resources(adapter);
+ err = atl1e_setup_ring_resources(adapter);
+ if (unlikely(err))
+ return err;
+
+ err = atl1e_request_irq(adapter);
+ if (unlikely(err))
+ goto err_req_irq;
+
+ err = atl1e_up(adapter);
+ if (unlikely(err))
+ goto err_up;
+
+ return 0;
+
+err_up:
+ atl1e_free_irq(adapter);
+err_req_irq:
+ atl1e_free_ring_resources(adapter);
+ atl1e_reset_hw(&adapter->hw);
+
+ return err;
+}
+
+/*
+ * atl1e_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1e_close(struct net_device *netdev)
+{
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+ atl1e_down(adapter);
+ atl1e_free_irq(adapter);
+ atl1e_free_ring_resources(adapter);
+
+ return 0;
+}
+
+static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ struct atl1e_hw *hw = &adapter->hw;
+ u32 ctrl = 0;
+ u32 mac_ctrl_data = 0;
+ u32 wol_ctrl_data = 0;
+ u16 mii_advertise_data = 0;
+ u16 mii_bmsr_data = 0;
+ u16 mii_intr_status_data = 0;
+ u32 wufc = adapter->wol;
+ u32 i;
+#ifdef CONFIG_PM
+ int retval = 0;
+#endif
+
+ if (netif_running(netdev)) {
+ WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+ atl1e_down(adapter);
+ }
+ netif_device_detach(netdev);
+
+#ifdef CONFIG_PM
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+#endif
+
+ if (wufc) {
+ /* get link status */
+ atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+ atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+
+ mii_advertise_data = MII_AR_10T_HD_CAPS;
+
+ if ((atl1e_write_phy_reg(hw, MII_AT001_CR, 0) != 0) ||
+ (atl1e_write_phy_reg(hw,
+ MII_ADVERTISE, mii_advertise_data) != 0) ||
+ (atl1e_phy_commit(hw)) != 0) {
+ dev_dbg(&pdev->dev, "set phy register failed\n");
+ goto wol_dis;
+ }
+
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ /* turn on magic packet wol */
+ if (wufc & AT_WUFC_MAG)
+ wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+ if (wufc & AT_WUFC_LNKC) {
+ /* if orignal link status is link, just wait for retrive link */
+ if (mii_bmsr_data & BMSR_LSTATUS) {
+ for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+ msleep(100);
+ atl1e_read_phy_reg(hw, MII_BMSR,
+ (u16 *)&mii_bmsr_data);
+ if (mii_bmsr_data & BMSR_LSTATUS)
+ break;
+ }
+
+ if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
+ dev_dbg(&pdev->dev,
+ "%s: Link may change"
+ "when suspend\n",
+ atl1e_driver_name);
+ }
+ wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+ /* only link up can wake up */
+ if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) {
+ dev_dbg(&pdev->dev, "%s: read write phy "
+ "register failed.\n",
+ atl1e_driver_name);
+ goto wol_dis;
+ }
+ }
+ /* clear phy interrupt */
+ atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data);
+ /* Config MAC Ctrl register */
+ mac_ctrl_data = MAC_CTRL_RX_EN;
+ /* set to 10/100M halt duplex */
+ mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT;
+ mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+ MAC_CTRL_PRMLEN_MASK) <<
+ MAC_CTRL_PRMLEN_SHIFT);
+
+ if (adapter->vlgrp)
+ mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+ /* magic packet maybe Broadcast&multicast&Unicast frame */
+ if (wufc & AT_WUFC_MAG)
+ mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+ dev_dbg(&pdev->dev,
+ "%s: suspend MAC=0x%x\n",
+ atl1e_driver_name, mac_ctrl_data);
+
+ AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+ AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+ /* pcie patch */
+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+ goto suspend_exit;
+ }
+wol_dis:
+
+ /* WOL disabled */
+ AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+ /* pcie patch */
+ ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+ ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+ AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+ atl1e_force_ps(hw);
+ hw->phy_configured = false; /* re-init PHY when resume */
+
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+suspend_exit:
+
+ if (netif_running(netdev))
+ atl1e_free_irq(adapter);
+
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int atl1e_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+ u32 err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "ATL1e: Cannot enable PCI"
+ " device from suspend\n");
+ return err;
+ }
+
+ pci_set_master(pdev);
+
+ AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+ if (netif_running(netdev))
+ err = atl1e_request_irq(adapter);
+ if (err)
+ return err;
+
+ atl1e_reset_hw(&adapter->hw);
+
+ if (netif_running(netdev))
+ atl1e_up(adapter);
+
+ netif_device_attach(netdev);
+
+ return 0;
+}
+#endif
+
+static void atl1e_shutdown(struct pci_dev *pdev)
+{
+ atl1e_suspend(pdev, PMSG_SUSPEND);
+}
+
+static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ pci_set_drvdata(pdev, netdev);
+
+ netdev->irq = pdev->irq;
+ netdev->open = &atl1e_open;
+ netdev->stop = &atl1e_close;
+ netdev->hard_start_xmit = &atl1e_xmit_frame;
+ netdev->get_stats = &atl1e_get_stats;
+ netdev->set_multicast_list = &atl1e_set_multi;
+ netdev->set_mac_address = &atl1e_set_mac_addr;
+ netdev->change_mtu = &atl1e_change_mtu;
+ netdev->do_ioctl = &atl1e_ioctl;
+ netdev->tx_timeout = &atl1e_tx_timeout;
+ netdev->watchdog_timeo = AT_TX_WATCHDOG;
+ netdev->vlan_rx_register = atl1e_vlan_rx_register;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ netdev->poll_controller = atl1e_netpoll;
+#endif
+ atl1e_set_ethtool_ops(netdev);
+
+ netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ netdev->features |= NETIF_F_LLTX;
+ netdev->features |= NETIF_F_TSO;
+ netdev->features |= NETIF_F_TSO6;
+
+ return 0;
+}
+
+/*
+ * atl1e_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1e_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1e_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1e_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct atl1e_adapter *adapter = NULL;
+ static int cards_found;
+
+ int err = 0;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "cannot enable PCI device\n");
+ return err;
+ }
+
+ /*
+ * The atl1e chip can DMA to 64-bit addresses, but it uses a single
+ * shared register for the high 32 bits, so only a single, aligned,
+ * 4 GB physical address range can be used at a time.
+ *
+ * Supporting 64-bit DMA on this hardware is more trouble than it's
+ * worth. It is far easier to limit to 32-bit DMA than update
+ * various kernel subsystems to support the mechanics required by a
+ * fixed-high-32-bit system.
+ */
+ if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
+ (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+ dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+ goto err_dma;
+ }
+
+ err = pci_request_regions(pdev, atl1e_driver_name);
+ if (err) {
+ dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+ goto err_pci_reg;
+ }
+
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
+ if (netdev == NULL) {
+ err = -ENOMEM;
+ dev_err(&pdev->dev, "etherdev alloc failed\n");
+ goto err_alloc_etherdev;
+ }
+
+ err = atl1e_init_netdev(netdev, pdev);
+ if (err) {
+ dev_err(&pdev->dev, "init netdevice failed\n");
+ goto err_init_netdev;
+ }
+ adapter = netdev_priv(netdev);
+ adapter->bd_number = cards_found;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.adapter = adapter;
+ adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0);
+ if (!adapter->hw.hw_addr) {
+ err = -EIO;
+ dev_err(&pdev->dev, "cannot map device registers\n");
+ goto err_ioremap;
+ }
+ netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+ /* init mii data */
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = atl1e_mdio_read;
+ adapter->mii.mdio_write = atl1e_mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+
+ netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
+
+ init_timer(&adapter->phy_config_timer);
+ adapter->phy_config_timer.function = &atl1e_phy_config;
+ adapter->phy_config_timer.data = (unsigned long) adapter;
+
+ /* get user settings */
+ atl1e_check_options(adapter);
+ /*
+ * Mark all PCI regions associated with PCI device
+ * pdev as being reserved by owner atl1e_driver_name
+ * Enables bus-mastering on the device and calls
+ * pcibios_set_master to do the needed arch specific settings
+ */
+ atl1e_setup_pcicmd(pdev);
+ /* setup the private structure */
+ err = atl1e_sw_init(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "net device private data init failed\n");
+ goto err_sw_init;
+ }
+
+ /* Init GPHY as early as possible due to power saving issue */
+ spin_lock(&adapter->mdio_lock);
+ atl1e_phy_init(&adapter->hw);
+ spin_unlock(&adapter->mdio_lock);
+ /* reset the controller to
+ * put the device in a known good starting state */
+ err = atl1e_reset_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_reset;
+ }
+
+ if (atl1e_read_mac_addr(&adapter->hw) != 0) {
+ err = -EIO;
+ dev_err(&pdev->dev, "get mac address failed\n");
+ goto err_eeprom;
+ }
+
+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+ dev_dbg(&pdev->dev, "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
+ adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+ adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+ adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+ INIT_WORK(&adapter->reset_task, atl1e_reset_task);
+ INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "register netdevice failed\n");
+ goto err_register;
+ }
+
+ /* assume we have no link for now */
+ netif_stop_queue(netdev);
+ netif_carrier_off(netdev);
+
+ cards_found++;
+
+ return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+ iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+ pci_disable_device(pdev);
+ return err;
+}
+
+/*
+ * atl1e_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1e_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1e_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+ /*
+ * flush_scheduled work may reschedule our watchdog task, so
+ * explicitly disable watchdog tasks from being rescheduled
+ */
+ set_bit(__AT_DOWN, &adapter->flags);
+
+ atl1e_del_timer(adapter);
+ atl1e_cancel_work(adapter);
+
+ unregister_netdev(netdev);
+ atl1e_free_ring_resources(adapter);
+ atl1e_force_ps(&adapter->hw);
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+}
+
+/*
+ * atl1e_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t
+atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev))
+ atl1e_down(adapter);
+
+ pci_disable_device(pdev);
+
+ /* Request a slot slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1e_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ if (pci_enable_device(pdev)) {
+ dev_err(&pdev->dev,
+ "ATL1e: Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_set_master(pdev);
+
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ atl1e_reset_hw(&adapter->hw);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1e_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1e_resume routine.
+ */
+static void atl1e_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1e_adapter *adapter = netdev->priv;
+
+ if (netif_running(netdev)) {
+ if (atl1e_up(adapter)) {
+ dev_err(&pdev->dev,
+ "ATL1e: can't bring device back up after reset\n");
+ return;
+ }
+ }
+
+ netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1e_err_handler = {
+ .error_detected = atl1e_io_error_detected,
+ .slot_reset = atl1e_io_slot_reset,
+ .resume = atl1e_io_resume,
+};
+
+static struct pci_driver atl1e_driver = {
+ .name = atl1e_driver_name,
+ .id_table = atl1e_pci_tbl,
+ .probe = atl1e_probe,
+ .remove = __devexit_p(atl1e_remove),
+ /* Power Managment Hooks */
+#ifdef CONFIG_PM
+ .suspend = atl1e_suspend,
+ .resume = atl1e_resume,
+#endif
+ .shutdown = atl1e_shutdown,
+ .err_handler = &atl1e_err_handler
+};
+
+/*
+ * atl1e_init_module - Driver Registration Routine
+ *
+ * atl1e_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1e_init_module(void)
+{
+ return pci_register_driver(&atl1e_driver);
+}
+
+/*
+ * atl1e_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1e_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1e_exit_module(void)
+{
+ pci_unregister_driver(&atl1e_driver);
+}
+
+module_init(atl1e_init_module);
+module_exit(atl1e_exit_module);
diff --git a/drivers/net/atl1e/atl1e_param.c b/drivers/net/atl1e/atl1e_param.c
new file mode 100644
index 00000000000..f72abb34b0c
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_param.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/netdevice.h>
+
+#include "atl1e.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define ATL1E_MAX_NIC 32
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
+
+#define ATL1E_PARAM(x, desc) \
+ static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+ static int num_##x; \
+ module_param_array_named(x, x, int, &num_##x, 0); \
+ MODULE_PARM_DESC(x, desc);
+
+/* Transmit Memory count
+ *
+ * Valid Range: 64-2048
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_TX_DESC_CNT 32
+#define ATL1E_MAX_TX_DESC_CNT 1020
+#define ATL1E_DEFAULT_TX_DESC_CNT 128
+ATL1E_PARAM(tx_desc_cnt, "Transmit description count");
+
+/* Receive Memory Block Count
+ *
+ * Valid Range: 16-512
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */
+#define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */
+#define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */
+ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)");
+
+/* User Specified MediaType Override
+ *
+ * Valid Range: 0-5
+ * - 0 - auto-negotiate at all supported speeds
+ * - 1 - only link at 100Mbps Full Duplex
+ * - 2 - only link at 100Mbps Half Duplex
+ * - 3 - only link at 10Mbps Full Duplex
+ * - 4 - only link at 10Mbps Half Duplex
+ * Default Value: 0
+ */
+
+ATL1E_PARAM(media_type, "MediaType Select");
+
+/* Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 45000(90ms)
+ */
+#define INT_MOD_DEFAULT_CNT 100 /* 200us */
+#define INT_MOD_MAX_CNT 65000
+#define INT_MOD_MIN_CNT 50
+ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer");
+
+#define AUTONEG_ADV_DEFAULT 0x2F
+#define AUTONEG_ADV_MASK 0x2F
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
+
+#define FLASH_VENDOR_DEFAULT 0
+#define FLASH_VENDOR_MIN 0
+#define FLASH_VENDOR_MAX 2
+
+struct atl1e_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct atl1e_opt_list { int i; char *str; } *p;
+ } l;
+ } arg;
+};
+
+static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct pci_dev *pdev)
+{
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ dev_info(&pdev->dev, "%s Enabled\n", opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ dev_info(&pdev->dev, "%s Disabled\n", opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ dev_info(&pdev->dev, "%s set to %i\n", opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option:{
+ int i;
+ struct atl1e_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ dev_info(&pdev->dev, "%s\n",
+ ent->str);
+ return 0;
+ }
+ }
+ break;
+ }
+ default:
+ BUG();
+ }
+
+ dev_info(&pdev->dev, "Invalid %s specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*
+ * atl1e_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int bd = adapter->bd_number;
+ if (bd >= ATL1E_MAX_NIC) {
+ dev_notice(&pdev->dev, "no configuration for board #%i\n", bd);
+ dev_notice(&pdev->dev, "Using defaults for all values\n");
+ }
+
+ { /* Transmit Ring Size */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Transmit Ddescription Count",
+ .err = "using default of "
+ __MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT),
+ .def = ATL1E_DEFAULT_TX_DESC_CNT,
+ .arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT,
+ .max = ATL1E_MAX_TX_DESC_CNT} }
+ };
+ int val;
+ if (num_tx_desc_cnt > bd) {
+ val = tx_desc_cnt[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->tx_ring.count = (u16) val & 0xFFFC;
+ } else
+ adapter->tx_ring.count = (u16)opt.def;
+ }
+
+ { /* Receive Memory Block Count */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Memory size of rx buffer(KB)",
+ .err = "using default of "
+ __MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE),
+ .def = ATL1E_DEFAULT_RX_MEM_SIZE,
+ .arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE,
+ .max = ATL1E_MAX_RX_MEM_SIZE} }
+ };
+ int val;
+ if (num_rx_mem_size > bd) {
+ val = rx_mem_size[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->rx_ring.page_size = (u32)val * 1024;
+ } else {
+ adapter->rx_ring.page_size = (u32)opt.def * 1024;
+ }
+ }
+
+ { /* Interrupt Moderate Timer */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Interrupt Moderate Timer",
+ .err = "using default of "
+ __MODULE_STRING(INT_MOD_DEFAULT_CNT),
+ .def = INT_MOD_DEFAULT_CNT,
+ .arg = { .r = { .min = INT_MOD_MIN_CNT,
+ .max = INT_MOD_MAX_CNT} }
+ } ;
+ int val;
+ if (num_int_mod_timer > bd) {
+ val = int_mod_timer[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->hw.imt = (u16) val;
+ } else
+ adapter->hw.imt = (u16)(opt.def);
+ }
+
+ { /* MediaType */
+ struct atl1e_option opt = {
+ .type = range_option,
+ .name = "Speed/Duplex Selection",
+ .err = "using default of "
+ __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR),
+ .def = MEDIA_TYPE_AUTO_SENSOR,
+ .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR,
+ .max = MEDIA_TYPE_10M_HALF} }
+ } ;
+ int val;
+ if (num_media_type > bd) {
+ val = media_type[bd];
+ atl1e_validate_option(&val, &opt, pdev);
+ adapter->hw.media_type = (u16) val;
+ } else
+ adapter->hw.media_type = (u16)(opt.def);
+
+ }
+}
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 3e22e7817bc..f12e3d12474 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1308,7 +1308,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
dev_info(&adapter->pdev->dev, "link is down\n");
adapter->link_speed = SPEED_0;
netif_carrier_off(netdev);
- netif_stop_queue(netdev);
}
return 0;
}
@@ -1358,7 +1357,6 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
if (!netif_carrier_ok(netdev)) {
/* Link down -> Up */
netif_carrier_on(netdev);
- netif_wake_queue(netdev);
}
return 0;
}
@@ -2627,6 +2625,7 @@ static s32 atl1_up(struct atl1_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies);
atlx_irq_enable(adapter);
atl1_check_link(adapter);
+ netif_start_queue(netdev);
return 0;
err_up:
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 3ab61e40e86..cb8be490e5a 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -911,9 +911,8 @@ au1000_adjust_link(struct net_device *dev)
if(phydev->link != aup->old_link) {
// link state changed
- if (phydev->link) // link went up
- netif_tx_schedule_all(dev);
- else { // link went down
+ if (!phydev->link) {
+ /* link went down */
aup->old_speed = 0;
aup->old_duplex = -1;
}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index a6a3da89f59..a8ec60e1ed7 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -357,7 +357,6 @@ static void bfin_mac_adjust_link(struct net_device *dev)
if (!lp->old_link) {
new_state = 1;
lp->old_link = 1;
- netif_tx_schedule_all(dev);
}
} else if (lp->old_link) {
new_state = 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 9737c06045d..a641eeaa2a2 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5041,6 +5041,7 @@ static int bond_check_params(struct bond_params *params)
}
static struct lock_class_key bonding_netdev_xmit_lock_key;
+static struct lock_class_key bonding_netdev_addr_lock_key;
static void bond_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -5052,6 +5053,8 @@ static void bond_set_lockdep_class_one(struct net_device *dev,
static void bond_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &bonding_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fbd4280c102..a7800e55909 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -945,10 +945,8 @@ static void cpmac_adjust_link(struct net_device *dev)
if (!priv->oldlink) {
new_state = 1;
priv->oldlink = 1;
- netif_tx_schedule_all(dev);
}
} else if (priv->oldlink) {
- netif_tx_stop_all_queues(dev);
new_state = 1;
priv->oldlink = 0;
priv->oldspeed = 0;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 952e10d686e..0b0f1c407a7 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -888,19 +888,22 @@ dm9000_rx(struct net_device *dev)
dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
}
- if (rxhdr.RxStatus & 0xbf) {
+ /* rxhdr.RxStatus is identical to RSR register. */
+ if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
+ RSR_PLE | RSR_RWTO |
+ RSR_LCS | RSR_RF)) {
GoodPacket = false;
- if (rxhdr.RxStatus & 0x01) {
+ if (rxhdr.RxStatus & RSR_FOE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "fifo error\n");
dev->stats.rx_fifo_errors++;
}
- if (rxhdr.RxStatus & 0x02) {
+ if (rxhdr.RxStatus & RSR_CE) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "crc error\n");
dev->stats.rx_crc_errors++;
}
- if (rxhdr.RxStatus & 0x80) {
+ if (rxhdr.RxStatus & RSR_RF) {
if (netif_msg_rx_err(db))
dev_dbg(db->dev, "length error\n");
dev->stats.rx_length_errors++;
@@ -1067,7 +1070,7 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
/* Fill the phyxcer register into REG_0C */
iow(db, DM9000_EPAR, DM9000_PHY | reg);
- iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */
+ iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock,flags);
@@ -1118,7 +1121,7 @@ dm9000_phy_write(struct net_device *dev,
iow(db, DM9000_EPDRL, value);
iow(db, DM9000_EPDRH, value >> 8);
- iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */
+ iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */
writeb(reg_save, db->io_addr);
spin_unlock_irqrestore(&db->lock, flags);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 31feae1ea39..19e317eaf5b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -90,10 +90,13 @@ struct e1000_adapter;
#define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
#define PFX "e1000: "
-#define DPRINTK(nlevel, klevel, fmt, args...) \
- (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
- printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
- __FUNCTION__ , ## args))
+
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+do { \
+ if (NETIF_MSG_##nlevel & adapter->msg_enable) \
+ printk(KERN_##klevel PFX "%s: %s: " fmt, \
+ adapter->netdev->name, __func__, ##args); \
+} while (0)
#define E1000_MAX_INTR 10
@@ -151,9 +154,9 @@ struct e1000_adapter;
#define E1000_MASTER_SLAVE e1000_ms_hw_default
#endif
-#define E1000_MNG_VLAN_NONE -1
+#define E1000_MNG_VLAN_NONE (-1)
/* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
+#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
/* wrapper around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer */
@@ -165,9 +168,13 @@ struct e1000_buffer {
u16 next_to_watch;
};
+struct e1000_ps_page {
+ struct page *ps_page[PS_PAGE_BUFFERS];
+};
-struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
-struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma {
+ u64 ps_page_dma[PS_PAGE_BUFFERS];
+};
struct e1000_tx_ring {
/* pointer to the descriptor ring memory */
@@ -217,13 +224,13 @@ struct e1000_rx_ring {
u16 rdt;
};
-#define E1000_DESC_UNUSED(R) \
- ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
- (R)->next_to_clean - (R)->next_to_use - 1)
+#define E1000_DESC_UNUSED(R) \
+ ((((R)->next_to_clean > (R)->next_to_use) \
+ ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
-#define E1000_RX_DESC_PS(R, i) \
+#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
-#define E1000_RX_DESC_EXT(R, i) \
+#define E1000_RX_DESC_EXT(R, i) \
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
@@ -246,9 +253,7 @@ struct e1000_adapter {
u16 link_speed;
u16 link_duplex;
spinlock_t stats_lock;
-#ifdef CONFIG_E1000_NAPI
spinlock_t tx_queue_lock;
-#endif
unsigned int total_tx_bytes;
unsigned int total_tx_packets;
unsigned int total_rx_bytes;
@@ -286,22 +291,16 @@ struct e1000_adapter {
bool detect_tx_hung;
/* RX */
-#ifdef CONFIG_E1000_NAPI
- bool (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
-#else
- bool (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-#endif
- void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count);
+ bool (*clean_rx)(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
+ void (*alloc_rx_buf)(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
-#ifdef CONFIG_E1000_NAPI
struct napi_struct napi;
struct net_device *polling_netdev; /* One per active queue */
-#endif
+
int num_tx_queues;
int num_rx_queues;
@@ -317,7 +316,6 @@ struct e1000_adapter {
u64 gorcl_old;
u16 rx_ps_bsize0;
-
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
@@ -342,6 +340,10 @@ struct e1000_adapter {
bool quad_port_a;
unsigned long flags;
u32 eeprom_wol;
+
+ /* for ioport free */
+ int bars;
+ int need_ioport;
};
enum e1000_state_t {
@@ -353,9 +355,18 @@ enum e1000_state_t {
extern char e1000_driver_name[];
extern const char e1000_driver_version[];
+extern int e1000_up(struct e1000_adapter *adapter);
+extern void e1000_down(struct e1000_adapter *adapter);
+extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+extern void e1000_reset(struct e1000_adapter *adapter);
+extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_update_stats(struct e1000_adapter *adapter);
extern void e1000_power_up_phy(struct e1000_adapter *);
extern void e1000_set_ethtool_ops(struct net_device *netdev);
extern void e1000_check_options(struct e1000_adapter *adapter);
-
#endif /* _E1000_H_ */
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index a3f6a9c72ec..6a3893acfe0 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -29,21 +29,8 @@
/* ethtool support for e1000 */
#include "e1000.h"
-
#include <asm/uaccess.h>
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-
-
struct e1000_stats {
char stat_string[ETH_GSTRING_LEN];
int sizeof_stat;
@@ -112,8 +99,8 @@ static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
};
#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test)
-static int
-e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -162,7 +149,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->transceiver = XCVR_EXTERNAL;
}
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
+ if (er32(STATUS) & E1000_STATUS_LU) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
@@ -185,8 +172,8 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static int
-e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -231,9 +218,8 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
return 0;
}
-static void
-e1000_get_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+static void e1000_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -251,9 +237,8 @@ e1000_get_pauseparam(struct net_device *netdev,
}
}
-static int
-e1000_set_pauseparam(struct net_device *netdev,
- struct ethtool_pauseparam *pause)
+static int e1000_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -289,15 +274,13 @@ e1000_set_pauseparam(struct net_device *netdev,
return retval;
}
-static u32
-e1000_get_rx_csum(struct net_device *netdev)
+static u32 e1000_get_rx_csum(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
return adapter->rx_csum;
}
-static int
-e1000_set_rx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
@@ -309,18 +292,17 @@ e1000_set_rx_csum(struct net_device *netdev, u32 data)
return 0;
}
-static u32
-e1000_get_tx_csum(struct net_device *netdev)
+static u32 e1000_get_tx_csum(struct net_device *netdev)
{
return (netdev->features & NETIF_F_HW_CSUM) != 0;
}
-static int
-e1000_set_tx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
- if (adapter->hw.mac_type < e1000_82543) {
+ if (hw->mac_type < e1000_82543) {
if (!data)
return -EINVAL;
return 0;
@@ -334,12 +316,13 @@ e1000_set_tx_csum(struct net_device *netdev, u32 data)
return 0;
}
-static int
-e1000_set_tso(struct net_device *netdev, u32 data)
+static int e1000_set_tso(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if ((adapter->hw.mac_type < e1000_82544) ||
- (adapter->hw.mac_type == e1000_82547))
+ struct e1000_hw *hw = &adapter->hw;
+
+ if ((hw->mac_type < e1000_82544) ||
+ (hw->mac_type == e1000_82547))
return data ? -EINVAL : 0;
if (data)
@@ -357,30 +340,26 @@ e1000_set_tso(struct net_device *netdev, u32 data)
return 0;
}
-static u32
-e1000_get_msglevel(struct net_device *netdev)
+static u32 e1000_get_msglevel(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
return adapter->msg_enable;
}
-static void
-e1000_set_msglevel(struct net_device *netdev, u32 data)
+static void e1000_set_msglevel(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->msg_enable = data;
}
-static int
-e1000_get_regs_len(struct net_device *netdev)
+static int e1000_get_regs_len(struct net_device *netdev)
{
#define E1000_REGS_LEN 32
return E1000_REGS_LEN * sizeof(u32);
}
-static void
-e1000_get_regs(struct net_device *netdev,
- struct ethtool_regs *regs, void *p)
+static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
+ void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -391,22 +370,22 @@ e1000_get_regs(struct net_device *netdev,
regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
- regs_buff[0] = E1000_READ_REG(hw, CTRL);
- regs_buff[1] = E1000_READ_REG(hw, STATUS);
+ regs_buff[0] = er32(CTRL);
+ regs_buff[1] = er32(STATUS);
- regs_buff[2] = E1000_READ_REG(hw, RCTL);
- regs_buff[3] = E1000_READ_REG(hw, RDLEN);
- regs_buff[4] = E1000_READ_REG(hw, RDH);
- regs_buff[5] = E1000_READ_REG(hw, RDT);
- regs_buff[6] = E1000_READ_REG(hw, RDTR);
+ regs_buff[2] = er32(RCTL);
+ regs_buff[3] = er32(RDLEN);
+ regs_buff[4] = er32(RDH);
+ regs_buff[5] = er32(RDT);
+ regs_buff[6] = er32(RDTR);
- regs_buff[7] = E1000_READ_REG(hw, TCTL);
- regs_buff[8] = E1000_READ_REG(hw, TDLEN);
- regs_buff[9] = E1000_READ_REG(hw, TDH);
- regs_buff[10] = E1000_READ_REG(hw, TDT);
- regs_buff[11] = E1000_READ_REG(hw, TIDV);
+ regs_buff[7] = er32(TCTL);
+ regs_buff[8] = er32(TDLEN);
+ regs_buff[9] = er32(TDH);
+ regs_buff[10] = er32(TDT);
+ regs_buff[11] = er32(TIDV);
- regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
+ regs_buff[12] = hw->phy_type; /* PHY type (IGP=1, M88=0) */
if (hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
@@ -464,20 +443,20 @@ e1000_get_regs(struct net_device *netdev,
if (hw->mac_type >= e1000_82540 &&
hw->mac_type < e1000_82571 &&
hw->media_type == e1000_media_type_copper) {
- regs_buff[26] = E1000_READ_REG(hw, MANC);
+ regs_buff[26] = er32(MANC);
}
}
-static int
-e1000_get_eeprom_len(struct net_device *netdev)
+static int e1000_get_eeprom_len(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- return adapter->hw.eeprom.word_size * 2;
+ struct e1000_hw *hw = &adapter->hw;
+
+ return hw->eeprom.word_size * 2;
}
-static int
-e1000_get_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_get_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -504,10 +483,12 @@ e1000_get_eeprom(struct net_device *netdev,
last_word - first_word + 1,
eeprom_buff);
else {
- for (i = 0; i < last_word - first_word + 1; i++)
- if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
- &eeprom_buff[i])))
+ for (i = 0; i < last_word - first_word + 1; i++) {
+ ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+ &eeprom_buff[i]);
+ if (ret_val)
break;
+ }
}
/* Device's eeprom is always little-endian, word addressable */
@@ -521,9 +502,8 @@ e1000_get_eeprom(struct net_device *netdev,
return ret_val;
}
-static int
-e1000_set_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -584,11 +564,11 @@ e1000_set_eeprom(struct net_device *netdev,
return ret_val;
}
-static void
-e1000_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *drvinfo)
+static void e1000_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
char firmware_version[32];
u16 eeprom_data;
@@ -597,8 +577,8 @@ e1000_get_drvinfo(struct net_device *netdev,
/* EEPROM image version # is reported as firmware version # for
* 8257{1|2|3} controllers */
- e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
- switch (adapter->hw.mac_type) {
+ e1000_read_eeprom(hw, 5, 1, &eeprom_data);
+ switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
case e1000_82573:
@@ -619,12 +599,12 @@ e1000_get_drvinfo(struct net_device *netdev,
drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
}
-static void
-e1000_get_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+static void e1000_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_mac_type mac_type = adapter->hw.mac_type;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_mac_type mac_type = hw->mac_type;
struct e1000_tx_ring *txdr = adapter->tx_ring;
struct e1000_rx_ring *rxdr = adapter->rx_ring;
@@ -640,12 +620,12 @@ e1000_get_ringparam(struct net_device *netdev,
ring->rx_jumbo_pending = 0;
}
-static int
-e1000_set_ringparam(struct net_device *netdev,
- struct ethtool_ringparam *ring)
+static int e1000_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_mac_type mac_type = adapter->hw.mac_type;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_mac_type mac_type = hw->mac_type;
struct e1000_tx_ring *txdr, *tx_old;
struct e1000_rx_ring *rxdr, *rx_old;
int i, err;
@@ -691,9 +671,11 @@ e1000_set_ringparam(struct net_device *netdev,
if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
- if ((err = e1000_setup_all_rx_resources(adapter)))
+ err = e1000_setup_all_rx_resources(adapter);
+ if (err)
goto err_setup_rx;
- if ((err = e1000_setup_all_tx_resources(adapter)))
+ err = e1000_setup_all_tx_resources(adapter);
+ if (err)
goto err_setup_tx;
/* save the new, restore the old in order to free it,
@@ -707,7 +689,8 @@ e1000_set_ringparam(struct net_device *netdev,
kfree(rx_old);
adapter->rx_ring = rxdr;
adapter->tx_ring = txdr;
- if ((err = e1000_up(adapter)))
+ err = e1000_up(adapter);
+ if (err)
goto err_setup;
}
@@ -728,12 +711,13 @@ err_setup:
return err;
}
-static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
- int reg, u32 mask, u32 write)
+static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
{
+ struct e1000_hw *hw = &adapter->hw;
static const u32 test[] =
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
- u8 __iomem *address = adapter->hw.hw_addr + reg;
+ u8 __iomem *address = hw->hw_addr + reg;
u32 read;
int i;
@@ -751,10 +735,11 @@ static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
return false;
}
-static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
- int reg, u32 mask, u32 write)
+static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
{
- u8 __iomem *address = adapter->hw.hw_addr + reg;
+ struct e1000_hw *hw = &adapter->hw;
+ u8 __iomem *address = hw->hw_addr + reg;
u32 read;
writel(write & mask, address);
@@ -772,7 +757,7 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
#define REG_PATTERN_TEST(reg, mask, write) \
do { \
if (reg_pattern_test(adapter, data, \
- (adapter->hw.mac_type >= e1000_82543) \
+ (hw->mac_type >= e1000_82543) \
? E1000_##reg : E1000_82542_##reg, \
mask, write)) \
return 1; \
@@ -781,22 +766,22 @@ static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
#define REG_SET_AND_CHECK(reg, mask, write) \
do { \
if (reg_set_and_check(adapter, data, \
- (adapter->hw.mac_type >= e1000_82543) \
+ (hw->mac_type >= e1000_82543) \
? E1000_##reg : E1000_82542_##reg, \
mask, write)) \
return 1; \
} while (0)
-static int
-e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
{
u32 value, before, after;
u32 i, toggle;
+ struct e1000_hw *hw = &adapter->hw;
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
/* there are several bits on newer hardware that are r/w */
case e1000_82571:
case e1000_82572:
@@ -812,10 +797,10 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
break;
}
- before = E1000_READ_REG(&adapter->hw, STATUS);
- value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
- E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
- after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
+ before = er32(STATUS);
+ value = (er32(STATUS) & toggle);
+ ew32(STATUS, toggle);
+ after = er32(STATUS) & toggle;
if (value != after) {
DPRINTK(DRV, ERR, "failed STATUS register test got: "
"0x%08X expected: 0x%08X\n", after, value);
@@ -823,9 +808,9 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
return 1;
}
/* restore previous status */
- E1000_WRITE_REG(&adapter->hw, STATUS, before);
+ ew32(STATUS, before);
- if (adapter->hw.mac_type != e1000_ich8lan) {
+ if (hw->mac_type != e1000_ich8lan) {
REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
@@ -845,20 +830,20 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
- before = (adapter->hw.mac_type == e1000_ich8lan ?
+ before = (hw->mac_type == e1000_ich8lan ?
0x06C3B33E : 0x06DFB3FE);
REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
- if (adapter->hw.mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- if (adapter->hw.mac_type != e1000_ich8lan)
+ if (hw->mac_type != e1000_ich8lan)
REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- value = (adapter->hw.mac_type == e1000_ich8lan ?
+ value = (hw->mac_type == e1000_ich8lan ?
E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
for (i = 0; i < value; i++) {
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -874,7 +859,7 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
}
- value = (adapter->hw.mac_type == e1000_ich8lan ?
+ value = (hw->mac_type == e1000_ich8lan ?
E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
for (i = 0; i < value; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
@@ -883,9 +868,9 @@ e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
return 0;
}
-static int
-e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 temp;
u16 checksum = 0;
u16 i;
@@ -893,7 +878,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
*data = 0;
/* Read and add up the contents of the EEPROM */
for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
@@ -901,30 +886,30 @@ e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
}
/* If Checksum is not Correct return error else test passed */
- if ((checksum != (u16) EEPROM_SUM) && !(*data))
+ if ((checksum != (u16)EEPROM_SUM) && !(*data))
*data = 2;
return *data;
}
-static irqreturn_t
-e1000_test_intr(int irq, void *data)
+static irqreturn_t e1000_test_intr(int irq, void *data)
{
- struct net_device *netdev = (struct net_device *) data;
+ struct net_device *netdev = (struct net_device *)data;
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
- adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
+ adapter->test_icr |= er32(ICR);
return IRQ_HANDLED;
}
-static int
-e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
{
struct net_device *netdev = adapter->netdev;
u32 mask, i = 0;
bool shared_int = true;
u32 irq = adapter->pdev->irq;
+ struct e1000_hw *hw = &adapter->hw;
*data = 0;
@@ -942,13 +927,13 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
(shared_int ? "shared" : "unshared"));
/* Disable all the interrupts */
- E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ ew32(IMC, 0xFFFFFFFF);
msleep(10);
/* Test each interrupt */
for (; i < 10; i++) {
- if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
+ if (hw->mac_type == e1000_ich8lan && i == 8)
continue;
/* Interrupt to test */
@@ -962,8 +947,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC, mask);
- E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ ew32(IMC, mask);
+ ew32(ICS, mask);
msleep(10);
if (adapter->test_icr & mask) {
@@ -979,8 +964,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMS, mask);
- E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ ew32(IMS, mask);
+ ew32(ICS, mask);
msleep(10);
if (!(adapter->test_icr & mask)) {
@@ -996,8 +981,8 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF);
- E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
+ ew32(IMC, ~mask & 0x00007FFF);
+ ew32(ICS, ~mask & 0x00007FFF);
msleep(10);
if (adapter->test_icr) {
@@ -1008,7 +993,7 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
}
/* Disable all the interrupts */
- E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+ ew32(IMC, 0xFFFFFFFF);
msleep(10);
/* Unhook test interrupt handler */
@@ -1017,8 +1002,7 @@ e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
return *data;
}
-static void
-e1000_free_desc_rings(struct e1000_adapter *adapter)
+static void e1000_free_desc_rings(struct e1000_adapter *adapter)
{
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
@@ -1064,9 +1048,9 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
return;
}
-static int
-e1000_setup_desc_rings(struct e1000_adapter *adapter)
+static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
@@ -1078,41 +1062,39 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
if (!txdr->count)
txdr->count = E1000_DEFAULT_TXD;
- if (!(txdr->buffer_info = kcalloc(txdr->count,
- sizeof(struct e1000_buffer),
- GFP_KERNEL))) {
+ txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_buffer),
+ GFP_KERNEL);
+ if (!txdr->buffer_info) {
ret_val = 1;
goto err_nomem;
}
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
txdr->size = ALIGN(txdr->size, 4096);
- if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size,
- &txdr->dma))) {
+ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+ if (!txdr->desc) {
ret_val = 2;
goto err_nomem;
}
memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = txdr->next_to_clean = 0;
- E1000_WRITE_REG(&adapter->hw, TDBAL,
- ((u64) txdr->dma & 0x00000000FFFFFFFF));
- E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
- E1000_WRITE_REG(&adapter->hw, TDLEN,
- txdr->count * sizeof(struct e1000_tx_desc));
- E1000_WRITE_REG(&adapter->hw, TDH, 0);
- E1000_WRITE_REG(&adapter->hw, TDT, 0);
- E1000_WRITE_REG(&adapter->hw, TCTL,
- E1000_TCTL_PSP | E1000_TCTL_EN |
- E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
- E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+ ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
+ ew32(TDBAH, ((u64)txdr->dma >> 32));
+ ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc));
+ ew32(TDH, 0);
+ ew32(TDT, 0);
+ ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN |
+ E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+ E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
for (i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
- if (!(skb = alloc_skb(size, GFP_KERNEL))) {
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb) {
ret_val = 3;
goto err_nomem;
}
@@ -1135,40 +1117,40 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
if (!rxdr->count)
rxdr->count = E1000_DEFAULT_RXD;
- if (!(rxdr->buffer_info = kcalloc(rxdr->count,
- sizeof(struct e1000_buffer),
- GFP_KERNEL))) {
+ rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
+ GFP_KERNEL);
+ if (!rxdr->buffer_info) {
ret_val = 4;
goto err_nomem;
}
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+ if (!rxdr->desc) {
ret_val = 5;
goto err_nomem;
}
memset(rxdr->desc, 0, rxdr->size);
rxdr->next_to_use = rxdr->next_to_clean = 0;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
- E1000_WRITE_REG(&adapter->hw, RDBAL,
- ((u64) rxdr->dma & 0xFFFFFFFF));
- E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
- E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
- E1000_WRITE_REG(&adapter->hw, RDH, 0);
- E1000_WRITE_REG(&adapter->hw, RDT, 0);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
+ ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF));
+ ew32(RDBAH, ((u64)rxdr->dma >> 32));
+ ew32(RDLEN, rxdr->size);
+ ew32(RDH, 0);
+ ew32(RDT, 0);
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
+ ew32(RCTL, rctl);
for (i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
- GFP_KERNEL))) {
+ skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
+ if (!skb) {
ret_val = 6;
goto err_nomem;
}
@@ -1189,73 +1171,74 @@ err_nomem:
return ret_val;
}
-static void
-e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
- e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
- e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
- e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
- e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
+ e1000_write_phy_reg(hw, 29, 0x001F);
+ e1000_write_phy_reg(hw, 30, 0x8FFC);
+ e1000_write_phy_reg(hw, 29, 0x001A);
+ e1000_write_phy_reg(hw, 30, 0x8FF0);
}
-static void
-e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_reg;
/* Because we reset the PHY above, we need to re-force TX_CLK in the
* Extended PHY Specific Control Register to 25MHz clock. This
* value defaults back to a 2.5MHz clock when the PHY is reset.
*/
- e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_EPSCR_TX_CLK_25;
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
/* In addition, because of the s/w reset above, we need to enable
* CRS on TX. This must be set for both full and half duplex
* operation.
*/
- e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_PHY_SPEC_CTRL, phy_reg);
}
-static int
-e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg;
u16 phy_reg;
/* Setup the Device Control Register for PHY loopback test. */
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */
E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ ew32(CTRL, ctrl_reg);
/* Read the PHY Specific Control Register (0x10) */
- e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
/* Clear Auto-Crossover bits in PHY Specific Control Register
* (bits 6:5).
*/
phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
- e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
/* Perform software reset on the PHY */
- e1000_phy_reset(&adapter->hw);
+ e1000_phy_reset(hw);
/* Have to setup TX_CLK and TX_CRS after software reset */
e1000_phy_reset_clk_and_crs(adapter);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x8100);
/* Wait for reset to complete. */
udelay(500);
@@ -1267,55 +1250,55 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
e1000_phy_disable_receiver(adapter);
/* Set the loopback bit in the PHY control register. */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
/* Setup TX_CLK and TX_CRS one more time. */
e1000_phy_reset_clk_and_crs(adapter);
/* Check Phy Configuration */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
if (phy_reg != 0x4100)
return 9;
- e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
if (phy_reg != 0x0070)
return 10;
- e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
+ e1000_read_phy_reg(hw, 29, &phy_reg);
if (phy_reg != 0x001A)
return 11;
return 0;
}
-static int
-e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg = 0;
u32 stat_reg = 0;
- adapter->hw.autoneg = false;
+ hw->autoneg = false;
- if (adapter->hw.phy_type == e1000_phy_m88) {
+ if (hw->phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x9140);
/* autoneg off */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
- } else if (adapter->hw.phy_type == e1000_phy_gg82563)
- e1000_write_phy_reg(&adapter->hw,
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x8140);
+ } else if (hw->phy_type == e1000_phy_gg82563)
+ e1000_write_phy_reg(hw,
GG82563_PHY_KMRN_MODE_CTRL,
0x1CC);
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
- if (adapter->hw.phy_type == e1000_phy_ife) {
+ if (hw->phy_type == e1000_phy_ife) {
/* force 100, set loopback */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x6100);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x6100);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
@@ -1325,10 +1308,10 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_FD); /* Force Duplex to FULL */
} else {
/* force 1000, set loopback */
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
/* Now set up the MAC to the same speed/duplex as the PHY. */
- ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl_reg = er32(CTRL);
ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
@@ -1336,23 +1319,23 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_FD); /* Force Duplex to FULL */
}
- if (adapter->hw.media_type == e1000_media_type_copper &&
- adapter->hw.phy_type == e1000_phy_m88)
+ if (hw->media_type == e1000_media_type_copper &&
+ hw->phy_type == e1000_phy_m88)
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
- stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
+ stat_reg = er32(STATUS);
if ((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+ ew32(CTRL, ctrl_reg);
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if (adapter->hw.phy_type == e1000_phy_m88)
+ if (hw->phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
@@ -1360,15 +1343,15 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
return 0;
}
-static int
-e1000_set_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_reg = 0;
u16 count = 0;
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82543:
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
@@ -1402,9 +1385,9 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
*/
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
phy_reg |= MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
return 0;
break;
}
@@ -1412,8 +1395,7 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
return 8;
}
-static int
-e1000_setup_loopback_test(struct e1000_adapter *adapter)
+static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
@@ -1431,14 +1413,14 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
case e1000_82572:
#define E1000_SERDES_LB_ON 0x410
e1000_set_phy_loopback(adapter);
- E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+ ew32(SCTL, E1000_SERDES_LB_ON);
msleep(10);
return 0;
break;
default:
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
return 0;
}
} else if (hw->media_type == e1000_media_type_copper)
@@ -1447,16 +1429,15 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
return 7;
}
-static void
-e1000_loopback_cleanup(struct e1000_adapter *adapter)
+static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
u16 phy_reg;
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
switch (hw->mac_type) {
case e1000_82571:
@@ -1464,7 +1445,7 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
if (hw->media_type == e1000_media_type_fiber ||
hw->media_type == e1000_media_type_internal_serdes) {
#define E1000_SERDES_LB_OFF 0x400
- E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+ ew32(SCTL, E1000_SERDES_LB_OFF);
msleep(10);
break;
}
@@ -1489,8 +1470,8 @@ e1000_loopback_cleanup(struct e1000_adapter *adapter)
}
}
-static void
-e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static void e1000_create_lbtest_frame(struct sk_buff *skb,
+ unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
frame_size &= ~1;
@@ -1499,8 +1480,8 @@ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
}
-static int
-e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int e1000_check_lbtest_frame(struct sk_buff *skb,
+ unsigned int frame_size)
{
frame_size &= ~1;
if (*(skb->data + 3) == 0xFF) {
@@ -1512,16 +1493,16 @@ e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
return 13;
}
-static int
-e1000_run_loopback_test(struct e1000_adapter *adapter)
+static int e1000_run_loopback_test(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
int i, j, k, l, lc, good_cnt, ret_val=0;
unsigned long time;
- E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
+ ew32(RDT, rxdr->count - 1);
/* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
@@ -1544,7 +1525,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
PCI_DMA_TODEVICE);
if (unlikely(++k == txdr->count)) k = 0;
}
- E1000_WRITE_REG(&adapter->hw, TDT, k);
+ ew32(TDT, k);
msleep(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
@@ -1577,21 +1558,24 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
return ret_val;
}
-static int
-e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* PHY loopback cannot be performed if SoL/IDER
* sessions are active */
- if (e1000_check_phy_reset_block(&adapter->hw)) {
+ if (e1000_check_phy_reset_block(hw)) {
DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
"when SoL/IDER is active.\n");
*data = 0;
goto out;
}
- if ((*data = e1000_setup_desc_rings(adapter)))
+ *data = e1000_setup_desc_rings(adapter);
+ if (*data)
goto out;
- if ((*data = e1000_setup_loopback_test(adapter)))
+ *data = e1000_setup_loopback_test(adapter);
+ if (*data)
goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
@@ -1602,38 +1586,37 @@ out:
return *data;
}
-static int
-e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
{
+ struct e1000_hw *hw = &adapter->hw;
*data = 0;
- if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ if (hw->media_type == e1000_media_type_internal_serdes) {
int i = 0;
- adapter->hw.serdes_link_down = true;
+ hw->serdes_link_down = true;
/* On some blade server designs, link establishment
* could take as long as 2-3 minutes */
do {
- e1000_check_for_link(&adapter->hw);
- if (!adapter->hw.serdes_link_down)
+ e1000_check_for_link(hw);
+ if (!hw->serdes_link_down)
return *data;
msleep(20);
} while (i++ < 3750);
*data = 1;
} else {
- e1000_check_for_link(&adapter->hw);
- if (adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ e1000_check_for_link(hw);
+ if (hw->autoneg) /* if auto_neg is set wait for it */
msleep(4000);
- if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ if (!(er32(STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
}
return *data;
}
-static int
-e1000_get_sset_count(struct net_device *netdev, int sset)
+static int e1000_get_sset_count(struct net_device *netdev, int sset)
{
switch (sset) {
case ETH_SS_TEST:
@@ -1645,11 +1628,11 @@ e1000_get_sset_count(struct net_device *netdev, int sset)
}
}
-static void
-e1000_diag_test(struct net_device *netdev,
- struct ethtool_test *eth_test, u64 *data)
+static void e1000_diag_test(struct net_device *netdev,
+ struct ethtool_test *eth_test, u64 *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
bool if_running = netif_running(netdev);
set_bit(__E1000_TESTING, &adapter->flags);
@@ -1657,9 +1640,9 @@ e1000_diag_test(struct net_device *netdev,
/* Offline tests */
/* save speed, duplex, autoneg settings */
- u16 autoneg_advertised = adapter->hw.autoneg_advertised;
- u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
- u8 autoneg = adapter->hw.autoneg;
+ u16 autoneg_advertised = hw->autoneg_advertised;
+ u8 forced_speed_duplex = hw->forced_speed_duplex;
+ u8 autoneg = hw->autoneg;
DPRINTK(HW, INFO, "offline testing starting\n");
@@ -1692,9 +1675,9 @@ e1000_diag_test(struct net_device *netdev,
eth_test->flags |= ETH_TEST_FL_FAILED;
/* restore speed, duplex, autoneg settings */
- adapter->hw.autoneg_advertised = autoneg_advertised;
- adapter->hw.forced_speed_duplex = forced_speed_duplex;
- adapter->hw.autoneg = autoneg;
+ hw->autoneg_advertised = autoneg_advertised;
+ hw->forced_speed_duplex = forced_speed_duplex;
+ hw->autoneg = autoneg;
e1000_reset(adapter);
clear_bit(__E1000_TESTING, &adapter->flags);
@@ -1717,7 +1700,8 @@ e1000_diag_test(struct net_device *netdev,
msleep_interruptible(4 * 1000);
}
-static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+static int e1000_wol_exclusion(struct e1000_adapter *adapter,
+ struct ethtool_wolinfo *wol)
{
struct e1000_hw *hw = &adapter->hw;
int retval = 1; /* fail by default */
@@ -1742,7 +1726,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
case E1000_DEV_ID_82571EB_SERDES:
case E1000_DEV_ID_82571EB_COPPER:
/* Wake events not supported on port B */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+ if (er32(STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
break;
}
@@ -1766,7 +1750,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
/* dual port cards only support WoL on port A from now on
* unless it was enabled in the eeprom for port B
* so exclude FUNC_1 ports from having WoL enabled */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 &&
+ if (er32(STATUS) & E1000_STATUS_FUNC_1 &&
!adapter->eeprom_wol) {
wol->supported = 0;
break;
@@ -1778,10 +1762,11 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol
return retval;
}
-static void
-e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static void e1000_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
wol->supported = WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC;
@@ -1793,7 +1778,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return;
/* apply any specific unsupported masks here */
- switch (adapter->hw.device_id) {
+ switch (hw->device_id) {
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* KSP3 does not suppport UCAST wake-ups */
wol->supported &= ~WAKE_UCAST;
@@ -1818,8 +1803,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return;
}
-static int
-e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -1863,61 +1847,60 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
/* bit defines for adapter->led_status */
#define E1000_LED_ON 0
-static void
-e1000_led_blink_callback(unsigned long data)
+static void e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_hw *hw = &adapter->hw;
if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
- e1000_led_off(&adapter->hw);
+ e1000_led_off(hw);
else
- e1000_led_on(&adapter->hw);
+ e1000_led_on(hw);
mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
}
-static int
-e1000_phys_id(struct net_device *netdev, u32 data)
+static int e1000_phys_id(struct net_device *netdev, u32 data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
if (!data)
data = INT_MAX;
- if (adapter->hw.mac_type < e1000_82571) {
+ if (hw->mac_type < e1000_82571) {
if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long) adapter;
+ adapter->blink_timer.data = (unsigned long)adapter;
}
- e1000_setup_led(&adapter->hw);
+ e1000_setup_led(hw);
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- } else if (adapter->hw.phy_type == e1000_phy_ife) {
+ } else if (hw->phy_type == e1000_phy_ife) {
if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long) adapter;
+ adapter->blink_timer.data = (unsigned long)adapter;
}
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
} else {
- e1000_blink_led_start(&adapter->hw);
+ e1000_blink_led_start(hw);
msleep_interruptible(data * 1000);
}
- e1000_led_off(&adapter->hw);
+ e1000_led_off(hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
- e1000_cleanup_led(&adapter->hw);
+ e1000_cleanup_led(hw);
return 0;
}
-static int
-e1000_nway_reset(struct net_device *netdev)
+static int e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
@@ -1925,9 +1908,8 @@ e1000_nway_reset(struct net_device *netdev)
return 0;
}
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats, u64 *data)
+static void e1000_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
int i;
@@ -1941,8 +1923,8 @@ e1000_get_ethtool_stats(struct net_device *netdev,
/* BUG_ON(i != E1000_STATS_LEN); */
}
-static void
-e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+static void e1000_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
{
u8 *p = data;
int i;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 9a4b6cbddf2..9d6edf3e73f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -42,48 +42,65 @@ static void e1000_release_software_semaphore(struct e1000_hw *hw);
static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
static s32 e1000_check_downshift(struct e1000_hw *hw);
-static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity);
static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
static void e1000_clear_vfta(struct e1000_hw *hw);
static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
- bool link_up);
+ bool link_up);
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+ u16 *max_length);
static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
static s32 e1000_get_software_flag(struct e1000_hw *hw);
static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
static s32 e1000_id_led_init(struct e1000_hw *hw);
-static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ u32 cnf_base_addr,
+ u32 cnf_size);
static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
static void e1000_init_rx_addrs(struct e1000_hw *hw);
static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
-static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum);
+static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw,
+ struct e1000_host_mng_command_header
+ *hdr);
static s32 e1000_mng_write_commit(struct e1000_hw *hw);
-static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info);
static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
-static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index,
+ u8 byte);
static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
-static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
-static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
-static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 *data);
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 data);
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static void e1000_release_software_flag(struct e1000_hw *hw);
static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
@@ -101,23 +118,21 @@ static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
- u16 count);
+ u16 count);
static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
- u16 offset, u16 words,
- u16 *data);
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
- u16 count);
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data);
+ u16 phy_data);
static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
- u16 *phy_data);
+ u16 *phy_data);
static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
static void e1000_release_eeprom(struct e1000_hw *hw);
@@ -127,8 +142,7 @@ static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
static s32 e1000_set_phy_mode(struct e1000_hw *hw);
static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
-static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
- u16 duplex);
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
/* IGP cable length table */
@@ -159,8 +173,7 @@ u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_set_phy_type(struct e1000_hw *hw)
+static s32 e1000_set_phy_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_phy_type");
@@ -210,8 +223,7 @@ e1000_set_phy_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_phy_init_script(struct e1000_hw *hw)
+static void e1000_phy_init_script(struct e1000_hw *hw)
{
u32 ret_val;
u16 phy_saved_data;
@@ -306,8 +318,7 @@ e1000_phy_init_script(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_set_mac_type(struct e1000_hw *hw)
+s32 e1000_set_mac_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_mac_type");
@@ -474,8 +485,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
* **************************************************************************/
-void
-e1000_set_media_type(struct e1000_hw *hw)
+void e1000_set_media_type(struct e1000_hw *hw)
{
u32 status;
@@ -510,7 +520,7 @@ e1000_set_media_type(struct e1000_hw *hw)
hw->media_type = e1000_media_type_copper;
break;
default:
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_TBIMODE) {
hw->media_type = e1000_media_type_fiber;
/* tbi_compatibility not valid on fiber */
@@ -528,8 +538,7 @@ e1000_set_media_type(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_reset_hw(struct e1000_hw *hw)
+s32 e1000_reset_hw(struct e1000_hw *hw)
{
u32 ctrl;
u32 ctrl_ext;
@@ -559,15 +568,15 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
/* Disable the Transmit and Receive units. Then delay to allow
* any pending transactions to complete before we hit the MAC with
* the global reset.
*/
- E1000_WRITE_REG(hw, RCTL, 0);
- E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, 0);
+ ew32(TCTL, E1000_TCTL_PSP);
+ E1000_WRITE_FLUSH();
/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
hw->tbi_compatibility_on = false;
@@ -577,11 +586,11 @@ e1000_reset_hw(struct e1000_hw *hw)
*/
msleep(10);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Must reset the PHY before resetting the MAC */
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
msleep(5);
}
@@ -590,12 +599,12 @@ e1000_reset_hw(struct e1000_hw *hw)
if (hw->mac_type == e1000_82573) {
timeout = 10;
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
do {
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
break;
@@ -610,9 +619,9 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Workaround for ICH8 bit corruption issue in FIFO memory */
if (hw->mac_type == e1000_ich8lan) {
/* Set Tx and Rx buffer allocation to 8k apiece. */
- E1000_WRITE_REG(hw, PBA, E1000_PBA_8K);
+ ew32(PBA, E1000_PBA_8K);
/* Set Packet Buffer Size to 16k. */
- E1000_WRITE_REG(hw, PBS, E1000_PBS_16K);
+ ew32(PBS, E1000_PBS_16K);
}
/* Issue a global reset to the MAC. This will reset the chip's
@@ -636,7 +645,7 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82545_rev_3:
case e1000_82546_rev_3:
/* Reset is performed on a shadow of the control register */
- E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
break;
case e1000_ich8lan:
if (!hw->phy_reset_disable &&
@@ -649,11 +658,11 @@ e1000_reset_hw(struct e1000_hw *hw)
}
e1000_get_software_flag(hw);
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(5);
break;
default:
- E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ ew32(CTRL, (ctrl | E1000_CTRL_RST));
break;
}
@@ -668,10 +677,10 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82544:
/* Wait for reset to complete */
udelay(10);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
/* Wait for EEPROM reload */
msleep(2);
break;
@@ -685,10 +694,10 @@ e1000_reset_hw(struct e1000_hw *hw)
case e1000_82573:
if (!e1000_is_onboard_nvm_eeprom(hw)) {
udelay(10);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
/* fall through */
default:
@@ -701,27 +710,27 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Disable HW ARPs on ASF enabled adapters */
if (hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
manc &= ~(E1000_MANC_ARP_EN);
- E1000_WRITE_REG(hw, MANC, manc);
+ ew32(MANC, manc);
}
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
e1000_phy_init_script(hw);
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
/* Clear any pending interrupt events. */
- icr = E1000_READ_REG(hw, ICR);
+ icr = er32(ICR);
/* If MWI was previously enabled, reenable it. */
if (hw->mac_type == e1000_82542_rev2_0) {
@@ -730,9 +739,9 @@ e1000_reset_hw(struct e1000_hw *hw)
}
if (hw->mac_type == e1000_ich8lan) {
- u32 kab = E1000_READ_REG(hw, KABGTXD);
+ u32 kab = er32(KABGTXD);
kab |= E1000_KABGTXD_BGSQLBIAS;
- E1000_WRITE_REG(hw, KABGTXD, kab);
+ ew32(KABGTXD, kab);
}
return E1000_SUCCESS;
@@ -747,8 +756,7 @@ e1000_reset_hw(struct e1000_hw *hw)
* This function contains hardware limitation workarounds for PCI-E adapters
*
*****************************************************************************/
-static void
-e1000_initialize_hardware_bits(struct e1000_hw *hw)
+static void e1000_initialize_hardware_bits(struct e1000_hw *hw)
{
if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
/* Settings common to all PCI-express silicon */
@@ -758,22 +766,22 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
u32 reg_txdctl, reg_txdctl1;
/* link autonegotiation/sync workarounds */
- reg_tarc0 = E1000_READ_REG(hw, TARC0);
+ reg_tarc0 = er32(TARC0);
reg_tarc0 &= ~((1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
/* Enable not-done TX descriptor counting */
- reg_txdctl = E1000_READ_REG(hw, TXDCTL);
+ reg_txdctl = er32(TXDCTL);
reg_txdctl |= E1000_TXDCTL_COUNT_DESC;
- E1000_WRITE_REG(hw, TXDCTL, reg_txdctl);
- reg_txdctl1 = E1000_READ_REG(hw, TXDCTL1);
+ ew32(TXDCTL, reg_txdctl);
+ reg_txdctl1 = er32(TXDCTL1);
reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC;
- E1000_WRITE_REG(hw, TXDCTL1, reg_txdctl1);
+ ew32(TXDCTL1, reg_txdctl1);
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
/* Clear PHY TX compatible mode bits */
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tarc1 = er32(TARC1);
reg_tarc1 &= ~((1 << 30)|(1 << 29));
/* link autonegotiation/sync workarounds */
@@ -783,25 +791,25 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
reg_tarc1 |= ((1 << 26)|(1 << 25)|(1 << 24));
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
+ reg_tctl = er32(TCTL);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
reg_tarc1 |= (1 << 28);
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
case e1000_82573:
- reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ reg_ctrl_ext = er32(CTRL_EXT);
reg_ctrl_ext &= ~(1 << 23);
reg_ctrl_ext |= (1 << 22);
/* TX byte count fix */
- reg_ctrl = E1000_READ_REG(hw, CTRL);
+ reg_ctrl = er32(CTRL);
reg_ctrl &= ~(1 << 29);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
- E1000_WRITE_REG(hw, CTRL, reg_ctrl);
+ ew32(CTRL_EXT, reg_ctrl_ext);
+ ew32(CTRL, reg_ctrl);
break;
case e1000_80003es2lan:
/* improve small packet performace for fiber/serdes */
@@ -811,14 +819,14 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
}
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tctl = er32(TCTL);
+ reg_tarc1 = er32(TARC1);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
reg_tarc1 |= (1 << 28);
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
case e1000_ich8lan:
/* Reduce concurrent DMA requests to 3 from 4 */
@@ -827,16 +835,16 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
(hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))
reg_tarc0 |= ((1 << 29)|(1 << 28));
- reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ reg_ctrl_ext = er32(CTRL_EXT);
reg_ctrl_ext |= (1 << 22);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
+ ew32(CTRL_EXT, reg_ctrl_ext);
/* workaround TX hang with TSO=on */
reg_tarc0 |= ((1 << 27)|(1 << 26)|(1 << 24)|(1 << 23));
/* Multiple read bit is reversed polarity */
- reg_tctl = E1000_READ_REG(hw, TCTL);
- reg_tarc1 = E1000_READ_REG(hw, TARC1);
+ reg_tctl = er32(TCTL);
+ reg_tarc1 = er32(TARC1);
if (reg_tctl & E1000_TCTL_MULR)
reg_tarc1 &= ~(1 << 28);
else
@@ -845,13 +853,13 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
/* workaround TX hang with TSO=on */
reg_tarc1 |= ((1 << 30)|(1 << 26)|(1 << 24));
- E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+ ew32(TARC1, reg_tarc1);
break;
default:
break;
}
- E1000_WRITE_REG(hw, TARC0, reg_tarc0);
+ ew32(TARC0, reg_tarc0);
}
}
@@ -866,8 +874,7 @@ e1000_initialize_hardware_bits(struct e1000_hw *hw)
* configuration and flow control settings. Clears all on-chip counters. Leaves
* the transmit and receive units disabled and uninitialized.
*****************************************************************************/
-s32
-e1000_init_hw(struct e1000_hw *hw)
+s32 e1000_init_hw(struct e1000_hw *hw)
{
u32 ctrl;
u32 i;
@@ -883,9 +890,9 @@ e1000_init_hw(struct e1000_hw *hw)
((hw->revision_id < 3) ||
((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) &&
(hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))) {
- reg_data = E1000_READ_REG(hw, STATUS);
+ reg_data = er32(STATUS);
reg_data &= ~0x80000000;
- E1000_WRITE_REG(hw, STATUS, reg_data);
+ ew32(STATUS, reg_data);
}
/* Initialize Identification LED */
@@ -906,7 +913,7 @@ e1000_init_hw(struct e1000_hw *hw)
/* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
if (hw->mac_type != e1000_ich8lan) {
if (hw->mac_type < e1000_82545_rev_3)
- E1000_WRITE_REG(hw, VET, 0);
+ ew32(VET, 0);
e1000_clear_vfta(hw);
}
@@ -914,8 +921,8 @@ e1000_init_hw(struct e1000_hw *hw)
if (hw->mac_type == e1000_82542_rev2_0) {
DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
e1000_pci_clear_mwi(hw);
- E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, E1000_RCTL_RST);
+ E1000_WRITE_FLUSH();
msleep(5);
}
@@ -926,8 +933,8 @@ e1000_init_hw(struct e1000_hw *hw)
/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
if (hw->mac_type == e1000_82542_rev2_0) {
- E1000_WRITE_REG(hw, RCTL, 0);
- E1000_WRITE_FLUSH(hw);
+ ew32(RCTL, 0);
+ E1000_WRITE_FLUSH();
msleep(1);
if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
e1000_pci_set_mwi(hw);
@@ -942,7 +949,7 @@ e1000_init_hw(struct e1000_hw *hw)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* use write flush to prevent Memory Write Block (MWB) from
* occuring when accessing our register space */
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/* Set the PCI priority bit correctly in the CTRL register. This
@@ -951,8 +958,8 @@ e1000_init_hw(struct e1000_hw *hw)
* 82542 and 82543 silicon.
*/
if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
- ctrl = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
}
switch (hw->mac_type) {
@@ -975,9 +982,9 @@ e1000_init_hw(struct e1000_hw *hw)
/* Set the transmit descriptor write-back policy */
if (hw->mac_type > e1000_82544) {
- ctrl = E1000_READ_REG(hw, TXDCTL);
+ ctrl = er32(TXDCTL);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- E1000_WRITE_REG(hw, TXDCTL, ctrl);
+ ew32(TXDCTL, ctrl);
}
if (hw->mac_type == e1000_82573) {
@@ -989,21 +996,21 @@ e1000_init_hw(struct e1000_hw *hw)
break;
case e1000_80003es2lan:
/* Enable retransmit on late collisions */
- reg_data = E1000_READ_REG(hw, TCTL);
+ reg_data = er32(TCTL);
reg_data |= E1000_TCTL_RTLC;
- E1000_WRITE_REG(hw, TCTL, reg_data);
+ ew32(TCTL, reg_data);
/* Configure Gigabit Carry Extend Padding */
- reg_data = E1000_READ_REG(hw, TCTL_EXT);
+ reg_data = er32(TCTL_EXT);
reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
- E1000_WRITE_REG(hw, TCTL_EXT, reg_data);
+ ew32(TCTL_EXT, reg_data);
/* Configure Transmit Inter-Packet Gap */
- reg_data = E1000_READ_REG(hw, TIPG);
+ reg_data = er32(TIPG);
reg_data &= ~E1000_TIPG_IPGT_MASK;
reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- E1000_WRITE_REG(hw, TIPG, reg_data);
+ ew32(TIPG, reg_data);
reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
reg_data &= ~0x00100000;
@@ -1012,17 +1019,17 @@ e1000_init_hw(struct e1000_hw *hw)
case e1000_82571:
case e1000_82572:
case e1000_ich8lan:
- ctrl = E1000_READ_REG(hw, TXDCTL1);
+ ctrl = er32(TXDCTL1);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+ ew32(TXDCTL1, ctrl);
break;
}
if (hw->mac_type == e1000_82573) {
- u32 gcr = E1000_READ_REG(hw, GCR);
+ u32 gcr = er32(GCR);
gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
- E1000_WRITE_REG(hw, GCR, gcr);
+ ew32(GCR, gcr);
}
/* Clear all of the statistics registers (clear on read). It is
@@ -1039,11 +1046,11 @@ e1000_init_hw(struct e1000_hw *hw)
if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
/* Relaxed ordering must be disabled to avoid a parity
* error crash in a PCI slot. */
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
return ret_val;
@@ -1054,8 +1061,7 @@ e1000_init_hw(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code.
*****************************************************************************/
-static s32
-e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
{
u16 eeprom_data;
s32 ret_val;
@@ -1100,8 +1106,7 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
* established. Assumes the hardware has previously been reset and the
* transmitter and receiver are not enabled.
*****************************************************************************/
-s32
-e1000_setup_link(struct e1000_hw *hw)
+s32 e1000_setup_link(struct e1000_hw *hw)
{
u32 ctrl_ext;
s32 ret_val;
@@ -1176,7 +1181,7 @@ e1000_setup_link(struct e1000_hw *hw)
}
ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
SWDPIO__EXT_SHIFT);
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
/* Call the necessary subroutine to configure the link. */
@@ -1193,12 +1198,12 @@ e1000_setup_link(struct e1000_hw *hw)
/* FCAL/H and FCT are hardcoded to standard values in e1000_ich8lan. */
if (hw->mac_type != e1000_ich8lan) {
- E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
- E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
- E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+ ew32(FCT, FLOW_CONTROL_TYPE);
+ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
}
- E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
+ ew32(FCTTV, hw->fc_pause_time);
/* Set the flow control receive threshold registers. Normally,
* these registers will be set to a default threshold that may be
@@ -1207,18 +1212,18 @@ e1000_setup_link(struct e1000_hw *hw)
* registers will be set to 0.
*/
if (!(hw->fc & E1000_FC_TX_PAUSE)) {
- E1000_WRITE_REG(hw, FCRTL, 0);
- E1000_WRITE_REG(hw, FCRTH, 0);
+ ew32(FCRTL, 0);
+ ew32(FCRTH, 0);
} else {
/* We need to set up the Receive Threshold high and low water marks
* as well as (optionally) enabling the transmission of XON frames.
*/
if (hw->fc_send_xon) {
- E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
- E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+ ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
+ ew32(FCRTH, hw->fc_high_water);
} else {
- E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
- E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+ ew32(FCRTL, hw->fc_low_water);
+ ew32(FCRTH, hw->fc_high_water);
}
}
return ret_val;
@@ -1233,8 +1238,7 @@ e1000_setup_link(struct e1000_hw *hw)
* link. Assumes the hardware has been previously reset and the transmitter
* and receiver are not enabled.
*****************************************************************************/
-static s32
-e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
{
u32 ctrl;
u32 status;
@@ -1251,7 +1255,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* loopback mode is disabled during initialization.
*/
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
- E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+ ew32(SCTL, E1000_DISABLE_SERDES_LOOPBACK);
/* On adapters with a MAC newer than 82544, SWDP 1 will be
* set when the optics detect a signal. On older adapters, it will be
@@ -1259,7 +1263,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* If we're on serdes media, adjust the output amplitude to value
* set in the EEPROM.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
if (hw->media_type == e1000_media_type_fiber)
signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
@@ -1330,9 +1334,9 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
*/
DEBUGOUT("Auto-negotiation enabled\n");
- E1000_WRITE_REG(hw, TXCW, txcw);
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(TXCW, txcw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
hw->txcw = txcw;
msleep(1);
@@ -1344,11 +1348,11 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
* For internal serdes, we just assume a signal is present, then poll.
*/
if (hw->media_type == e1000_media_type_internal_serdes ||
- (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
+ (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
DEBUGOUT("Looking for Link\n");
for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
msleep(10);
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_LU) break;
}
if (i == (LINK_UP_TIMEOUT / 10)) {
@@ -1380,8 +1384,7 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_copper_link_preconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -1389,7 +1392,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
DEBUGFUNC("e1000_copper_link_preconfig");
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* With 82543, we need to force speed and duplex on the MAC equal to what
* the PHY speed and duplex configuration is. In addition, we need to
* perform a hardware reset on the PHY to take it out of reset.
@@ -1397,10 +1400,10 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
if (hw->mac_type > e1000_82543) {
ctrl |= E1000_CTRL_SLU;
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
ret_val = e1000_phy_hw_reset(hw);
if (ret_val)
return ret_val;
@@ -1440,8 +1443,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_igp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
{
u32 led_ctrl;
s32 ret_val;
@@ -1462,10 +1464,10 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
msleep(15);
if (hw->mac_type != e1000_ich8lan) {
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
@@ -1587,8 +1589,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_ggp_setup(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1679,9 +1680,9 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- reg_data = E1000_READ_REG(hw, CTRL_EXT);
+ reg_data = er32(CTRL_EXT);
reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
- E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+ ew32(CTRL_EXT, reg_data);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
&phy_data);
@@ -1735,8 +1736,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1839,8 +1839,7 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*********************************************************************/
-static s32
-e1000_copper_link_autoneg(struct e1000_hw *hw)
+static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -1910,8 +1909,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_copper_link_postconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_copper_link_postconfig");
@@ -1948,8 +1946,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_setup_copper_link(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link(struct e1000_hw *hw)
{
s32 ret_val;
u16 i;
@@ -2062,8 +2059,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
{
s32 ret_val = E1000_SUCCESS;
u32 tipg;
@@ -2078,10 +2074,10 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
return ret_val;
/* Configure Transmit Inter-Packet Gap */
- tipg = E1000_READ_REG(hw, TIPG);
+ tipg = er32(TIPG);
tipg &= ~E1000_TIPG_IPGT_MASK;
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
@@ -2098,8 +2094,7 @@ e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
return ret_val;
}
-static s32
-e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 reg_data;
@@ -2114,10 +2109,10 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
return ret_val;
/* Configure Transmit Inter-Packet Gap */
- tipg = E1000_READ_REG(hw, TIPG);
+ tipg = er32(TIPG);
tipg &= ~E1000_TIPG_IPGT_MASK;
tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
@@ -2135,8 +2130,7 @@ e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-s32
-e1000_phy_setup_autoneg(struct e1000_hw *hw)
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_autoneg_adv_reg;
@@ -2284,8 +2278,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -2302,7 +2295,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
DEBUGOUT1("hw->fc = %d\n", hw->fc);
/* Read the Device Control Register. */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
@@ -2357,7 +2350,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
e1000_config_collision_dist(hw);
/* Write the configured values back to the Device Control Reg. */
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if ((hw->phy_type == e1000_phy_m88) ||
(hw->phy_type == e1000_phy_gg82563)) {
@@ -2535,8 +2528,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
* Link should have been established previously. Reads the speed and duplex
* information from the Device Status register.
******************************************************************************/
-void
-e1000_config_collision_dist(struct e1000_hw *hw)
+void e1000_config_collision_dist(struct e1000_hw *hw)
{
u32 tctl, coll_dist;
@@ -2547,13 +2539,13 @@ e1000_config_collision_dist(struct e1000_hw *hw)
else
coll_dist = E1000_COLLISION_DISTANCE;
- tctl = E1000_READ_REG(hw, TCTL);
+ tctl = er32(TCTL);
tctl &= ~E1000_TCTL_COLD;
tctl |= coll_dist << E1000_COLD_SHIFT;
- E1000_WRITE_REG(hw, TCTL, tctl);
- E1000_WRITE_FLUSH(hw);
+ ew32(TCTL, tctl);
+ E1000_WRITE_FLUSH();
}
/******************************************************************************
@@ -2565,8 +2557,7 @@ e1000_config_collision_dist(struct e1000_hw *hw)
* The contents of the PHY register containing the needed information need to
* be passed in.
******************************************************************************/
-static s32
-e1000_config_mac_to_phy(struct e1000_hw *hw)
+static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
{
u32 ctrl;
s32 ret_val;
@@ -2582,7 +2573,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
/* Read the Device Control Register and set the bits to Force Speed
* and Duplex.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
@@ -2609,7 +2600,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
ctrl |= E1000_CTRL_SPD_100;
/* Write the configured values back to the Device Control Reg. */
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -2624,15 +2615,14 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
* by the PHY rather than the MAC. Software must also configure these
* bits when link is forced on a fiber connection.
*****************************************************************************/
-s32
-e1000_force_mac_fc(struct e1000_hw *hw)
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
{
u32 ctrl;
DEBUGFUNC("e1000_force_mac_fc");
/* Get the current configuration of the Device Control Register */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Because we didn't get link via the internal auto-negotiation
* mechanism (we either forced link or we got link via PHY
@@ -2676,7 +2666,7 @@ e1000_force_mac_fc(struct e1000_hw *hw)
if (hw->mac_type == e1000_82542_rev2_0)
ctrl &= (~E1000_CTRL_TFCE);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -2691,8 +2681,7 @@ e1000_force_mac_fc(struct e1000_hw *hw)
* based on the flow control negotiated by the PHY. In TBI mode, the TFCE
* and RFCE bits will be automaticaly set to the negotiated flow control mode.
*****************************************************************************/
-static s32
-e1000_config_fc_after_link_up(struct e1000_hw *hw)
+static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_status_reg;
@@ -2896,8 +2885,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
*
* Called by any function that needs to check the link status of the adapter.
*****************************************************************************/
-s32
-e1000_check_for_link(struct e1000_hw *hw)
+s32 e1000_check_for_link(struct e1000_hw *hw)
{
u32 rxcw = 0;
u32 ctrl;
@@ -2910,8 +2898,8 @@ e1000_check_for_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_for_link");
- ctrl = E1000_READ_REG(hw, CTRL);
- status = E1000_READ_REG(hw, STATUS);
+ ctrl = er32(CTRL);
+ status = er32(STATUS);
/* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
* set when the optics detect a signal. On older adapters, it will be
@@ -2919,7 +2907,7 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if ((hw->media_type == e1000_media_type_fiber) ||
(hw->media_type == e1000_media_type_internal_serdes)) {
- rxcw = E1000_READ_REG(hw, RXCW);
+ rxcw = er32(RXCW);
if (hw->media_type == e1000_media_type_fiber) {
signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
@@ -2965,11 +2953,11 @@ e1000_check_for_link(struct e1000_hw *hw)
(!hw->autoneg) &&
(hw->forced_speed_duplex == e1000_10_full ||
hw->forced_speed_duplex == e1000_10_half)) {
- E1000_WRITE_REG(hw, IMC, 0xffffffff);
+ ew32(IMC, 0xffffffff);
ret_val = e1000_polarity_reversal_workaround(hw);
- icr = E1000_READ_REG(hw, ICR);
- E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
- E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+ icr = er32(ICR);
+ ew32(ICS, (icr & ~E1000_ICS_LSC));
+ ew32(IMS, IMS_ENABLE_MASK);
}
} else {
@@ -3034,9 +3022,9 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if (hw->tbi_compatibility_on) {
/* If we previously were in the mode, turn it off. */
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_SBP;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
hw->tbi_compatibility_on = false;
}
} else {
@@ -3047,9 +3035,9 @@ e1000_check_for_link(struct e1000_hw *hw)
*/
if (!hw->tbi_compatibility_on) {
hw->tbi_compatibility_on = true;
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_SBP;
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
}
}
@@ -3073,12 +3061,12 @@ e1000_check_for_link(struct e1000_hw *hw)
DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
- E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
+ ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
/* Force link-up and also force full-duplex. */
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
/* Configure Flow Control after forcing link up. */
ret_val = e1000_config_fc_after_link_up(hw);
@@ -3096,8 +3084,8 @@ e1000_check_for_link(struct e1000_hw *hw)
(hw->media_type == e1000_media_type_internal_serdes)) &&
(ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
- E1000_WRITE_REG(hw, TXCW, hw->txcw);
- E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+ ew32(TXCW, hw->txcw);
+ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
hw->serdes_link_down = false;
}
@@ -3105,10 +3093,10 @@ e1000_check_for_link(struct e1000_hw *hw)
* based on MAC synchronization for internal serdes media type.
*/
else if ((hw->media_type == e1000_media_type_internal_serdes) &&
- !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+ !(E1000_TXCW_ANE & er32(TXCW))) {
/* SYNCH bit and IV bit are sticky. */
udelay(10);
- if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+ if (E1000_RXCW_SYNCH & er32(RXCW)) {
if (!(rxcw & E1000_RXCW_IV)) {
hw->serdes_link_down = false;
DEBUGOUT("SERDES: Link is up.\n");
@@ -3119,8 +3107,8 @@ e1000_check_for_link(struct e1000_hw *hw)
}
}
if ((hw->media_type == e1000_media_type_internal_serdes) &&
- (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
- hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
+ (E1000_TXCW_ANE & er32(TXCW))) {
+ hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
}
return E1000_SUCCESS;
}
@@ -3132,10 +3120,7 @@ e1000_check_for_link(struct e1000_hw *hw)
* speed - Speed of the connection
* duplex - Duplex setting of the connection
*****************************************************************************/
-s32
-e1000_get_speed_and_duplex(struct e1000_hw *hw,
- u16 *speed,
- u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
{
u32 status;
s32 ret_val;
@@ -3144,7 +3129,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
DEBUGFUNC("e1000_get_speed_and_duplex");
if (hw->mac_type >= e1000_82543) {
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_SPEED_1000) {
*speed = SPEED_1000;
DEBUGOUT("1000 Mbs, ");
@@ -3214,8 +3199,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_wait_autoneg(struct e1000_hw *hw)
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
{
s32 ret_val;
u16 i;
@@ -3249,15 +3233,13 @@ e1000_wait_autoneg(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* ctrl - Device control register's current value
******************************************************************************/
-static void
-e1000_raise_mdi_clk(struct e1000_hw *hw,
- u32 *ctrl)
+static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
{
/* Raise the clock input to the Management Data Clock (by setting the MDC
* bit), and then delay 10 microseconds.
*/
- E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
udelay(10);
}
@@ -3267,15 +3249,13 @@ e1000_raise_mdi_clk(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* ctrl - Device control register's current value
******************************************************************************/
-static void
-e1000_lower_mdi_clk(struct e1000_hw *hw,
- u32 *ctrl)
+static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
{
/* Lower the clock input to the Management Data Clock (by clearing the MDC
* bit), and then delay 10 microseconds.
*/
- E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
udelay(10);
}
@@ -3288,10 +3268,7 @@ e1000_lower_mdi_clk(struct e1000_hw *hw,
*
* Bits are shifted out in MSB to LSB order.
******************************************************************************/
-static void
-e1000_shift_out_mdi_bits(struct e1000_hw *hw,
- u32 data,
- u16 count)
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
{
u32 ctrl;
u32 mask;
@@ -3303,7 +3280,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
mask = 0x01;
mask <<= (count - 1);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
@@ -3319,8 +3296,8 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
else
ctrl &= ~E1000_CTRL_MDIO;
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
udelay(10);
@@ -3338,8 +3315,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw,
*
* Bits are shifted in in MSB to LSB order.
******************************************************************************/
-static u16
-e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
{
u32 ctrl;
u16 data = 0;
@@ -3352,14 +3328,14 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
* by raising the input to the Management Data Clock (setting the MDC bit),
* and then reading the value of the MDIO bit.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
ctrl &= ~E1000_CTRL_MDIO_DIR;
ctrl &= ~E1000_CTRL_MDIO;
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
/* Raise and Lower the clock before reading in the data. This accounts for
* the turnaround bits. The first clock occurred when we clocked out the
@@ -3371,7 +3347,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
for (data = 0, i = 0; i < 16; i++) {
data = data << 1;
e1000_raise_mdi_clk(hw, &ctrl);
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
/* Check to see if we shifted in a "1". */
if (ctrl & E1000_CTRL_MDIO)
data |= 1;
@@ -3384,8 +3360,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw)
return data;
}
-static s32
-e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync = 0;
u32 swmask = mask;
@@ -3404,7 +3379,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
if (e1000_get_hw_eeprom_semaphore(hw))
return -E1000_ERR_SWFW_SYNC;
- swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+ swfw_sync = er32(SW_FW_SYNC);
if (!(swfw_sync & (fwmask | swmask))) {
break;
}
@@ -3422,14 +3397,13 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
}
swfw_sync |= swmask;
- E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+ ew32(SW_FW_SYNC, swfw_sync);
e1000_put_hw_eeprom_semaphore(hw);
return E1000_SUCCESS;
}
-static void
-e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
{
u32 swfw_sync;
u32 swmask = mask;
@@ -3451,9 +3425,9 @@ e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
/* empty */
- swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+ swfw_sync = er32(SW_FW_SYNC);
swfw_sync &= ~swmask;
- E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+ ew32(SW_FW_SYNC, swfw_sync);
e1000_put_hw_eeprom_semaphore(hw);
}
@@ -3464,10 +3438,7 @@ e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
* hw - Struct containing variables accessed by shared code
* reg_addr - address of the PHY register to read
******************************************************************************/
-s32
-e1000_read_phy_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 *phy_data)
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
{
u32 ret_val;
u16 swfw;
@@ -3475,7 +3446,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_read_phy_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3523,9 +3494,8 @@ e1000_read_phy_reg(struct e1000_hw *hw,
return ret_val;
}
-static s32
-e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 *phy_data)
+static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 *phy_data)
{
u32 i;
u32 mdic = 0;
@@ -3547,12 +3517,12 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
(phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_READ));
- E1000_WRITE_REG(hw, MDIC, mdic);
+ ew32(MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed */
for (i = 0; i < 64; i++) {
udelay(50);
- mdic = E1000_READ_REG(hw, MDIC);
+ mdic = er32(MDIC);
if (mdic & E1000_MDIC_READY) break;
}
if (!(mdic & E1000_MDIC_READY)) {
@@ -3563,7 +3533,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
DEBUGOUT("MDI Error\n");
return -E1000_ERR_PHY;
}
- *phy_data = (u16) mdic;
+ *phy_data = (u16)mdic;
} else {
/* We must first send a preamble through the MDIO pin to signal the
* beginning of an MII instruction. This is done by sending 32
@@ -3603,9 +3573,7 @@ e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
* reg_addr - address of the PHY register to write
* data - data to write to the PHY
******************************************************************************/
-s32
-e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data)
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
{
u32 ret_val;
u16 swfw;
@@ -3613,7 +3581,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
DEBUGFUNC("e1000_write_phy_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3661,9 +3629,8 @@ e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
return ret_val;
}
-static s32
-e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data)
+static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 phy_data)
{
u32 i;
u32 mdic = 0;
@@ -3681,17 +3648,17 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
* for the PHY register in the MDI Control register. The MAC will take
* care of interfacing with the PHY to send the desired data.
*/
- mdic = (((u32) phy_data) |
+ mdic = (((u32)phy_data) |
(reg_addr << E1000_MDIC_REG_SHIFT) |
(phy_addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_WRITE));
- E1000_WRITE_REG(hw, MDIC, mdic);
+ ew32(MDIC, mdic);
/* Poll the ready bit to see if the MDI read completed */
for (i = 0; i < 641; i++) {
udelay(5);
- mdic = E1000_READ_REG(hw, MDIC);
+ mdic = er32(MDIC);
if (mdic & E1000_MDIC_READY) break;
}
if (!(mdic & E1000_MDIC_READY)) {
@@ -3715,7 +3682,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
mdic <<= 16;
- mdic |= (u32) phy_data;
+ mdic |= (u32)phy_data;
e1000_shift_out_mdi_bits(hw, mdic, 32);
}
@@ -3723,17 +3690,14 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
return E1000_SUCCESS;
}
-static s32
-e1000_read_kmrn_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 *data)
+static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data)
{
u32 reg_val;
u16 swfw;
DEBUGFUNC("e1000_read_kmrn_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3745,28 +3709,25 @@ e1000_read_kmrn_reg(struct e1000_hw *hw,
reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
E1000_KUMCTRLSTA_OFFSET) |
E1000_KUMCTRLSTA_REN;
- E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+ ew32(KUMCTRLSTA, reg_val);
udelay(2);
/* Read the data returned */
- reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+ reg_val = er32(KUMCTRLSTA);
*data = (u16)reg_val;
e1000_swfw_sync_release(hw, swfw);
return E1000_SUCCESS;
}
-static s32
-e1000_write_kmrn_reg(struct e1000_hw *hw,
- u32 reg_addr,
- u16 data)
+static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data)
{
u32 reg_val;
u16 swfw;
DEBUGFUNC("e1000_write_kmrn_reg");
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3776,7 +3737,7 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
E1000_KUMCTRLSTA_OFFSET) | data;
- E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+ ew32(KUMCTRLSTA, reg_val);
udelay(2);
e1000_swfw_sync_release(hw, swfw);
@@ -3788,8 +3749,7 @@ e1000_write_kmrn_reg(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-s32
-e1000_phy_hw_reset(struct e1000_hw *hw)
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
u32 ctrl, ctrl_ext;
u32 led_ctrl;
@@ -3808,7 +3768,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if (hw->mac_type > e1000_82543) {
if ((hw->mac_type == e1000_80003es2lan) &&
- (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+ (er32(STATUS) & E1000_STATUS_FUNC_1)) {
swfw = E1000_SWFW_PHY1_SM;
} else {
swfw = E1000_SWFW_PHY0_SM;
@@ -3823,17 +3783,17 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
* and deassert. For e1000_82571 hardware and later, we instead delay
* for 50us between and 10ms after the deassertion.
*/
- ctrl = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
- E1000_WRITE_FLUSH(hw);
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
+ E1000_WRITE_FLUSH();
if (hw->mac_type < e1000_82571)
msleep(10);
else
udelay(100);
- E1000_WRITE_REG(hw, CTRL, ctrl);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
if (hw->mac_type >= e1000_82571)
mdelay(10);
@@ -3843,24 +3803,24 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
* bit to put the PHY into reset. Then, take it out of reset.
*/
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
msleep(10);
ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
udelay(150);
if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
/* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl = er32(LEDCTL);
led_ctrl &= IGP_ACTIVITY_LED_MASK;
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ ew32(LEDCTL, led_ctrl);
}
/* Wait for FW to finish PHY configuration. */
@@ -3882,8 +3842,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
*
* Sets bit 15 of the MII Control register
******************************************************************************/
-s32
-e1000_phy_reset(struct e1000_hw *hw)
+s32 e1000_phy_reset(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -3934,8 +3893,7 @@ e1000_phy_reset(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
-void
-e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+void e1000_phy_powerdown_workaround(struct e1000_hw *hw)
{
s32 reg;
u16 phy_data;
@@ -3948,8 +3906,8 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
do {
/* Disable link */
- reg = E1000_READ_REG(hw, PHY_CTRL);
- E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ reg = er32(PHY_CTRL);
+ ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
/* Write VR power-down enable - bits 9:8 should be 10b */
@@ -3964,8 +3922,8 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
break;
/* Issue PHY reset and repeat at most one more time */
- reg = E1000_READ_REG(hw, CTRL);
- E1000_WRITE_REG(hw, CTRL, reg | E1000_CTRL_PHY_RST);
+ reg = er32(CTRL);
+ ew32(CTRL, reg | E1000_CTRL_PHY_RST);
retry++;
} while (retry);
@@ -3987,8 +3945,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw)
*
* hw - struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
{
s32 ret_val;
s32 reg;
@@ -4024,8 +3981,8 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
mdelay(5);
}
/* Disable GigE link negotiation */
- reg = E1000_READ_REG(hw, PHY_CTRL);
- E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+ reg = er32(PHY_CTRL);
+ ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
/* unable to acquire PCS lock */
@@ -4040,8 +3997,7 @@ e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_detect_gig_phy(struct e1000_hw *hw)
+static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
{
s32 phy_init_status, ret_val;
u16 phy_id_high, phy_id_low;
@@ -4076,14 +4032,14 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- hw->phy_id = (u32) (phy_id_high << 16);
+ hw->phy_id = (u32)(phy_id_high << 16);
udelay(20);
ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
if (ret_val)
return ret_val;
- hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
- hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+ hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
+ hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
switch (hw->mac_type) {
case e1000_82543:
@@ -4136,8 +4092,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-static s32
-e1000_phy_reset_dsp(struct e1000_hw *hw)
+static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_phy_reset_dsp");
@@ -4163,9 +4118,8 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_igp_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data, min_length, max_length, average;
@@ -4240,9 +4194,8 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_ife_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4290,9 +4243,8 @@ e1000_phy_ife_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-static s32
-e1000_phy_m88_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4369,9 +4321,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* phy_info - PHY information structure
******************************************************************************/
-s32
-e1000_phy_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
{
s32 ret_val;
u16 phy_data;
@@ -4415,8 +4365,7 @@ e1000_phy_get_info(struct e1000_hw *hw,
return e1000_phy_m88_get_info(hw, phy_info);
}
-s32
-e1000_validate_mdi_setting(struct e1000_hw *hw)
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_validate_mdi_settings");
@@ -4436,11 +4385,10 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_init_eeprom_params(struct e1000_hw *hw)
+s32 e1000_init_eeprom_params(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd = E1000_READ_REG(hw, EECD);
+ u32 eecd = er32(EECD);
s32 ret_val = E1000_SUCCESS;
u16 eeprom_size;
@@ -4542,7 +4490,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
/* Ensure that the Autonomous FLASH update bit is cleared due to
* Flash update issue on parts which use a FLASH for NVM. */
eecd &= ~E1000_EECD_AUPDEN;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
break;
case e1000_80003es2lan:
@@ -4626,16 +4574,14 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/
-static void
-e1000_raise_ee_clk(struct e1000_hw *hw,
- u32 *eecd)
+static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
/* Raise the clock input to the EEPROM (by setting the SK bit), and then
* wait <delay> microseconds.
*/
*eecd = *eecd | E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, *eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
@@ -4645,16 +4591,14 @@ e1000_raise_ee_clk(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* eecd - EECD's current value
*****************************************************************************/
-static void
-e1000_lower_ee_clk(struct e1000_hw *hw,
- u32 *eecd)
+static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
* wait 50 microseconds.
*/
*eecd = *eecd & ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, *eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
@@ -4665,10 +4609,7 @@ e1000_lower_ee_clk(struct e1000_hw *hw,
* data - data to send to the EEPROM
* count - number of bits to shift out
*****************************************************************************/
-static void
-e1000_shift_out_ee_bits(struct e1000_hw *hw,
- u16 data,
- u16 count)
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
@@ -4679,7 +4620,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
* In order to do this, "data" must be broken down into bits.
*/
mask = 0x01 << (count - 1);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eeprom->type == e1000_eeprom_microwire) {
eecd &= ~E1000_EECD_DO;
} else if (eeprom->type == e1000_eeprom_spi) {
@@ -4696,8 +4637,8 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
if (data & mask)
eecd |= E1000_EECD_DI;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
@@ -4710,7 +4651,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
/* We leave the "DI" bit set to "0" when we leave this routine. */
eecd &= ~E1000_EECD_DI;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
/******************************************************************************
@@ -4718,9 +4659,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static u16
-e1000_shift_in_ee_bits(struct e1000_hw *hw,
- u16 count)
+static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
{
u32 eecd;
u32 i;
@@ -4733,7 +4672,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
* always be clear.
*/
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
data = 0;
@@ -4742,7 +4681,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
data = data << 1;
e1000_raise_ee_clk(hw, &eecd);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
eecd &= ~(E1000_EECD_DI);
if (eecd & E1000_EECD_DO)
@@ -4762,8 +4701,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw,
* Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
* function should be called before issuing a command to the EEPROM.
*****************************************************************************/
-static s32
-e1000_acquire_eeprom(struct e1000_hw *hw)
+static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd, i=0;
@@ -4772,23 +4710,23 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
return -E1000_ERR_SWFW_SYNC;
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (hw->mac_type != e1000_82573) {
/* Request EEPROM Access */
if (hw->mac_type > e1000_82544) {
eecd |= E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
- eecd = E1000_READ_REG(hw, EECD);
+ ew32(EECD, eecd);
+ eecd = er32(EECD);
while ((!(eecd & E1000_EECD_GNT)) &&
(i < E1000_EEPROM_GRANT_ATTEMPTS)) {
i++;
udelay(5);
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
}
if (!(eecd & E1000_EECD_GNT)) {
eecd &= ~E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
DEBUGOUT("Could not acquire EEPROM grant\n");
e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
return -E1000_ERR_EEPROM;
@@ -4801,15 +4739,15 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
if (eeprom->type == e1000_eeprom_microwire) {
/* Clear SK and DI */
eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
/* Set CS */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
} else if (eeprom->type == e1000_eeprom_spi) {
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
udelay(1);
}
@@ -4821,46 +4759,45 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_standby_eeprom(struct e1000_hw *hw)
+static void e1000_standby_eeprom(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eeprom->type == e1000_eeprom_microwire) {
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Clock high */
eecd |= E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Select EEPROM */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
/* Clock low */
eecd &= ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
} else if (eeprom->type == e1000_eeprom_spi) {
/* Toggle CS to flush commands */
eecd |= E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
eecd &= ~E1000_EECD_CS;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(eeprom->delay_usec);
}
}
@@ -4870,20 +4807,19 @@ e1000_standby_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_release_eeprom(struct e1000_hw *hw)
+static void e1000_release_eeprom(struct e1000_hw *hw)
{
u32 eecd;
DEBUGFUNC("e1000_release_eeprom");
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (hw->eeprom.type == e1000_eeprom_spi) {
eecd |= E1000_EECD_CS; /* Pull CS high */
eecd &= ~E1000_EECD_SK; /* Lower SCK */
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
udelay(hw->eeprom.delay_usec);
} else if (hw->eeprom.type == e1000_eeprom_microwire) {
@@ -4892,25 +4828,25 @@ e1000_release_eeprom(struct e1000_hw *hw)
/* CS on Microwire is active-high */
eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
/* Rising edge of clock */
eecd |= E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
/* Falling edge of clock */
eecd &= ~E1000_EECD_SK;
- E1000_WRITE_REG(hw, EECD, eecd);
- E1000_WRITE_FLUSH(hw);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
udelay(hw->eeprom.delay_usec);
}
/* Stop requesting EEPROM access */
if (hw->mac_type > e1000_82544) {
eecd &= ~E1000_EECD_REQ;
- E1000_WRITE_REG(hw, EECD, eecd);
+ ew32(EECD, eecd);
}
e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
@@ -4921,8 +4857,7 @@ e1000_release_eeprom(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_spi_eeprom_ready(struct e1000_hw *hw)
+static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
{
u16 retry_count = 0;
u8 spi_stat_reg;
@@ -4967,11 +4902,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-s32
-e1000_read_eeprom(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 i = 0;
@@ -5068,11 +4999,8 @@ e1000_read_eeprom(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_read_eeprom_eerd(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 i, eerd = 0;
s32 error = 0;
@@ -5081,13 +5009,13 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
E1000_EEPROM_RW_REG_START;
- E1000_WRITE_REG(hw, EERD, eerd);
+ ew32(EERD, eerd);
error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
if (error) {
break;
}
- data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+ data[i] = (er32(EERD) >> E1000_EEPROM_RW_REG_DATA);
}
@@ -5102,11 +5030,8 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_write_eeprom_eewr(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 register_value = 0;
u32 i = 0;
@@ -5125,7 +5050,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
break;
}
- E1000_WRITE_REG(hw, EEWR, register_value);
+ ew32(EEWR, register_value);
error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
@@ -5143,8 +5068,7 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
{
u32 attempts = 100000;
u32 i, reg = 0;
@@ -5152,9 +5076,9 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
for (i = 0; i < attempts; i++) {
if (eerd == E1000_EEPROM_POLL_READ)
- reg = E1000_READ_REG(hw, EERD);
+ reg = er32(EERD);
else
- reg = E1000_READ_REG(hw, EEWR);
+ reg = er32(EEWR);
if (reg & E1000_EEPROM_RW_REG_DONE) {
done = E1000_SUCCESS;
@@ -5171,8 +5095,7 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
*
* hw - Struct containing variables accessed by shared code
****************************************************************************/
-static bool
-e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
{
u32 eecd = 0;
@@ -5182,7 +5105,7 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
return false;
if (hw->mac_type == e1000_82573) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
/* Isolate bits 15 & 16 */
eecd = ((eecd >> 15) & 0x03);
@@ -5204,8 +5127,7 @@ e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
* If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
* valid.
*****************************************************************************/
-s32
-e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
{
u16 checksum = 0;
u16 i, eeprom_data;
@@ -5252,7 +5174,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
checksum += eeprom_data;
}
- if (checksum == (u16) EEPROM_SUM)
+ if (checksum == (u16)EEPROM_SUM)
return E1000_SUCCESS;
else {
DEBUGOUT("EEPROM Checksum Invalid\n");
@@ -5268,8 +5190,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
* Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
* Writes the difference to word offset 63 of the EEPROM.
*****************************************************************************/
-s32
-e1000_update_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
{
u32 ctrl_ext;
u16 checksum = 0;
@@ -5284,7 +5205,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
}
checksum += eeprom_data;
}
- checksum = (u16) EEPROM_SUM - checksum;
+ checksum = (u16)EEPROM_SUM - checksum;
if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM;
@@ -5294,9 +5215,9 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
e1000_commit_shadow_ram(hw);
/* Reload the EEPROM, or else modifications will not appear
* until after next adapter reset. */
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
msleep(10);
}
return E1000_SUCCESS;
@@ -5313,11 +5234,7 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
* If e1000_update_eeprom_checksum is not called after this function, the
* EEPROM will most likely contain an invalid checksum.
*****************************************************************************/
-s32
-e1000_write_eeprom(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
s32 status = 0;
@@ -5370,11 +5287,8 @@ e1000_write_eeprom(struct e1000_hw *hw,
* data - pointer to array of 8 bit words to be written to the EEPROM
*
*****************************************************************************/
-static s32
-e1000_write_eeprom_spi(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u16 widx = 0;
@@ -5436,11 +5350,8 @@ e1000_write_eeprom_spi(struct e1000_hw *hw,
* data - pointer to array of 16 bit words to be written to the EEPROM
*
*****************************************************************************/
-static s32
-e1000_write_eeprom_microwire(struct e1000_hw *hw,
- u16 offset,
- u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
u32 eecd;
@@ -5484,7 +5395,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
* If DO does not go high in 10 milliseconds, then error out.
*/
for (i = 0; i < 200; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if (eecd & E1000_EECD_DO) break;
udelay(50);
}
@@ -5523,8 +5434,7 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_commit_shadow_ram(struct e1000_hw *hw)
+static s32 e1000_commit_shadow_ram(struct e1000_hw *hw)
{
u32 attempts = 100000;
u32 eecd = 0;
@@ -5539,9 +5449,9 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
if (hw->mac_type == e1000_82573) {
/* The flop register will be used to determine if flash type is STM */
- flop = E1000_READ_REG(hw, FLOP);
+ flop = er32(FLOP);
for (i=0; i < attempts; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
}
@@ -5554,14 +5464,14 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* If STM opcode located in bits 15:8 of flop, reset firmware */
if ((flop & 0xFF00) == E1000_STM_OPCODE) {
- E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
+ ew32(HICR, E1000_HICR_FW_RESET);
}
/* Perform the flash update */
- E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
+ ew32(EECD, eecd | E1000_EECD_FLUPD);
for (i=0; i < attempts; i++) {
- eecd = E1000_READ_REG(hw, EECD);
+ eecd = er32(EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
}
@@ -5577,7 +5487,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* We're writing to the opposite bank so if we're on bank 1,
* write to bank 0 etc. We also need to erase the segment that
* is going to be written */
- if (!(E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL)) {
+ if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
new_bank_offset = hw->flash_bank_size * 2;
old_bank_offset = 0;
e1000_erase_ich8_4k_segment(hw, 1);
@@ -5687,8 +5597,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_read_mac_addr(struct e1000_hw * hw)
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
{
u16 offset;
u16 eeprom_data, i;
@@ -5701,8 +5610,8 @@ e1000_read_mac_addr(struct e1000_hw * hw)
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
- hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
- hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+ hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
+ hw->perm_mac_addr[i+1] = (u8)(eeprom_data >> 8);
}
switch (hw->mac_type) {
@@ -5712,7 +5621,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
case e1000_82546_rev_3:
case e1000_82571:
case e1000_80003es2lan:
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
hw->perm_mac_addr[5] ^= 0x01;
break;
}
@@ -5731,8 +5640,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
* of the receive addresss registers. Clears the multicast table. Assumes
* the receiver is in reset when the routine is called.
*****************************************************************************/
-static void
-e1000_init_rx_addrs(struct e1000_hw *hw)
+static void e1000_init_rx_addrs(struct e1000_hw *hw)
{
u32 i;
u32 rar_num;
@@ -5758,9 +5666,9 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
DEBUGOUT("Clearing RAR[1-15]\n");
for (i = 1; i < rar_num; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5770,9 +5678,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
* hw - Struct containing variables accessed by shared code
* mc_addr - the multicast address to hash
*****************************************************************************/
-u32
-e1000_hash_mc_addr(struct e1000_hw *hw,
- u8 *mc_addr)
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{
u32 hash_value = 0;
@@ -5787,37 +5693,37 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
case 0:
if (hw->mac_type == e1000_ich8lan) {
/* [47:38] i.e. 0x158 for above example address */
- hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+ hash_value = ((mc_addr[4] >> 6) | (((u16)mc_addr[5]) << 2));
} else {
/* [47:36] i.e. 0x563 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
}
break;
case 1:
if (hw->mac_type == e1000_ich8lan) {
/* [46:37] i.e. 0x2B1 for above example address */
- hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+ hash_value = ((mc_addr[4] >> 5) | (((u16)mc_addr[5]) << 3));
} else {
/* [46:35] i.e. 0xAC6 for above example address */
- hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
}
break;
case 2:
if (hw->mac_type == e1000_ich8lan) {
/*[45:36] i.e. 0x163 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
} else {
/* [45:34] i.e. 0x5D8 for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
}
break;
case 3:
if (hw->mac_type == e1000_ich8lan) {
/* [43:34] i.e. 0x18D for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
} else {
/* [43:32] i.e. 0x634 for above example address */
- hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
}
break;
}
@@ -5835,9 +5741,7 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
* hw - Struct containing variables accessed by shared code
* hash_value - Multicast address hash value
*****************************************************************************/
-void
-e1000_mta_set(struct e1000_hw *hw,
- u32 hash_value)
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
{
u32 hash_bit, hash_reg;
u32 mta;
@@ -5868,12 +5772,12 @@ e1000_mta_set(struct e1000_hw *hw,
if ((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
} else {
E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5884,20 +5788,16 @@ e1000_mta_set(struct e1000_hw *hw,
* addr - Address to put into receive address register
* index - Receive address register to write
*****************************************************************************/
-void
-e1000_rar_set(struct e1000_hw *hw,
- u8 *addr,
- u32 index)
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
{
u32 rar_low, rar_high;
/* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
- rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
* unit hang.
@@ -5930,9 +5830,9 @@ e1000_rar_set(struct e1000_hw *hw,
}
E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/******************************************************************************
@@ -5942,10 +5842,7 @@ e1000_rar_set(struct e1000_hw *hw,
* offset - Offset in VLAN filer table to write
* value - Value to write into VLAN filter table
*****************************************************************************/
-void
-e1000_write_vfta(struct e1000_hw *hw,
- u32 offset,
- u32 value)
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
{
u32 temp;
@@ -5955,12 +5852,12 @@ e1000_write_vfta(struct e1000_hw *hw,
if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
} else {
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
@@ -5969,8 +5866,7 @@ e1000_write_vfta(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_clear_vfta(struct e1000_hw *hw)
+static void e1000_clear_vfta(struct e1000_hw *hw)
{
u32 offset;
u32 vfta_value = 0;
@@ -5999,12 +5895,11 @@ e1000_clear_vfta(struct e1000_hw *hw)
* manageability unit */
vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
-static s32
-e1000_id_led_init(struct e1000_hw * hw)
+static s32 e1000_id_led_init(struct e1000_hw *hw)
{
u32 ledctl;
const u32 ledctl_mask = 0x000000FF;
@@ -6020,7 +5915,7 @@ e1000_id_led_init(struct e1000_hw * hw)
return E1000_SUCCESS;
}
- ledctl = E1000_READ_REG(hw, LEDCTL);
+ ledctl = er32(LEDCTL);
hw->ledctl_default = ledctl;
hw->ledctl_mode1 = hw->ledctl_default;
hw->ledctl_mode2 = hw->ledctl_default;
@@ -6086,8 +5981,7 @@ e1000_id_led_init(struct e1000_hw * hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_setup_led(struct e1000_hw *hw)
+s32 e1000_setup_led(struct e1000_hw *hw)
{
u32 ledctl;
s32 ret_val = E1000_SUCCESS;
@@ -6118,7 +6012,7 @@ e1000_setup_led(struct e1000_hw *hw)
/* Fall Through */
default:
if (hw->media_type == e1000_media_type_fiber) {
- ledctl = E1000_READ_REG(hw, LEDCTL);
+ ledctl = er32(LEDCTL);
/* Save current LEDCTL settings */
hw->ledctl_default = ledctl;
/* Turn off LED0 */
@@ -6127,9 +6021,9 @@ e1000_setup_led(struct e1000_hw *hw)
E1000_LEDCTL_LED0_MODE_MASK);
ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
E1000_LEDCTL_LED0_MODE_SHIFT);
- E1000_WRITE_REG(hw, LEDCTL, ledctl);
+ ew32(LEDCTL, ledctl);
} else if (hw->media_type == e1000_media_type_copper)
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+ ew32(LEDCTL, hw->ledctl_mode1);
break;
}
@@ -6145,8 +6039,7 @@ e1000_setup_led(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_blink_led_start(struct e1000_hw *hw)
+s32 e1000_blink_led_start(struct e1000_hw *hw)
{
s16 i;
u32 ledctl_blink = 0;
@@ -6170,7 +6063,7 @@ e1000_blink_led_start(struct e1000_hw *hw)
ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8));
}
- E1000_WRITE_REG(hw, LEDCTL, ledctl_blink);
+ ew32(LEDCTL, ledctl_blink);
return E1000_SUCCESS;
}
@@ -6180,8 +6073,7 @@ e1000_blink_led_start(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_cleanup_led(struct e1000_hw *hw)
+s32 e1000_cleanup_led(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
@@ -6210,7 +6102,7 @@ e1000_cleanup_led(struct e1000_hw *hw)
break;
}
/* Restore LEDCTL settings */
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
+ ew32(LEDCTL, hw->ledctl_default);
break;
}
@@ -6222,10 +6114,9 @@ e1000_cleanup_led(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_led_on(struct e1000_hw *hw)
+s32 e1000_led_on(struct e1000_hw *hw)
{
- u32 ctrl = E1000_READ_REG(hw, CTRL);
+ u32 ctrl = er32(CTRL);
DEBUGFUNC("e1000_led_on");
@@ -6257,13 +6148,13 @@ e1000_led_on(struct e1000_hw *hw)
e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
} else if (hw->media_type == e1000_media_type_copper) {
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
+ ew32(LEDCTL, hw->ledctl_mode2);
return E1000_SUCCESS;
}
break;
}
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -6273,10 +6164,9 @@ e1000_led_on(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-s32
-e1000_led_off(struct e1000_hw *hw)
+s32 e1000_led_off(struct e1000_hw *hw)
{
- u32 ctrl = E1000_READ_REG(hw, CTRL);
+ u32 ctrl = er32(CTRL);
DEBUGFUNC("e1000_led_off");
@@ -6308,13 +6198,13 @@ e1000_led_off(struct e1000_hw *hw)
e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
} else if (hw->media_type == e1000_media_type_copper) {
- E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+ ew32(LEDCTL, hw->ledctl_mode1);
return E1000_SUCCESS;
}
break;
}
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
return E1000_SUCCESS;
}
@@ -6324,98 +6214,97 @@ e1000_led_off(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static void
-e1000_clear_hw_cntrs(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
{
volatile u32 temp;
- temp = E1000_READ_REG(hw, CRCERRS);
- temp = E1000_READ_REG(hw, SYMERRS);
- temp = E1000_READ_REG(hw, MPC);
- temp = E1000_READ_REG(hw, SCC);
- temp = E1000_READ_REG(hw, ECOL);
- temp = E1000_READ_REG(hw, MCC);
- temp = E1000_READ_REG(hw, LATECOL);
- temp = E1000_READ_REG(hw, COLC);
- temp = E1000_READ_REG(hw, DC);
- temp = E1000_READ_REG(hw, SEC);
- temp = E1000_READ_REG(hw, RLEC);
- temp = E1000_READ_REG(hw, XONRXC);
- temp = E1000_READ_REG(hw, XONTXC);
- temp = E1000_READ_REG(hw, XOFFRXC);
- temp = E1000_READ_REG(hw, XOFFTXC);
- temp = E1000_READ_REG(hw, FCRUC);
+ temp = er32(CRCERRS);
+ temp = er32(SYMERRS);
+ temp = er32(MPC);
+ temp = er32(SCC);
+ temp = er32(ECOL);
+ temp = er32(MCC);
+ temp = er32(LATECOL);
+ temp = er32(COLC);
+ temp = er32(DC);
+ temp = er32(SEC);
+ temp = er32(RLEC);
+ temp = er32(XONRXC);
+ temp = er32(XONTXC);
+ temp = er32(XOFFRXC);
+ temp = er32(XOFFTXC);
+ temp = er32(FCRUC);
if (hw->mac_type != e1000_ich8lan) {
- temp = E1000_READ_REG(hw, PRC64);
- temp = E1000_READ_REG(hw, PRC127);
- temp = E1000_READ_REG(hw, PRC255);
- temp = E1000_READ_REG(hw, PRC511);
- temp = E1000_READ_REG(hw, PRC1023);
- temp = E1000_READ_REG(hw, PRC1522);
- }
-
- temp = E1000_READ_REG(hw, GPRC);
- temp = E1000_READ_REG(hw, BPRC);
- temp = E1000_READ_REG(hw, MPRC);
- temp = E1000_READ_REG(hw, GPTC);
- temp = E1000_READ_REG(hw, GORCL);
- temp = E1000_READ_REG(hw, GORCH);
- temp = E1000_READ_REG(hw, GOTCL);
- temp = E1000_READ_REG(hw, GOTCH);
- temp = E1000_READ_REG(hw, RNBC);
- temp = E1000_READ_REG(hw, RUC);
- temp = E1000_READ_REG(hw, RFC);
- temp = E1000_READ_REG(hw, ROC);
- temp = E1000_READ_REG(hw, RJC);
- temp = E1000_READ_REG(hw, TORL);
- temp = E1000_READ_REG(hw, TORH);
- temp = E1000_READ_REG(hw, TOTL);
- temp = E1000_READ_REG(hw, TOTH);
- temp = E1000_READ_REG(hw, TPR);
- temp = E1000_READ_REG(hw, TPT);
+ temp = er32(PRC64);
+ temp = er32(PRC127);
+ temp = er32(PRC255);
+ temp = er32(PRC511);
+ temp = er32(PRC1023);
+ temp = er32(PRC1522);
+ }
+
+ temp = er32(GPRC);
+ temp = er32(BPRC);
+ temp = er32(MPRC);
+ temp = er32(GPTC);
+ temp = er32(GORCL);
+ temp = er32(GORCH);
+ temp = er32(GOTCL);
+ temp = er32(GOTCH);
+ temp = er32(RNBC);
+ temp = er32(RUC);
+ temp = er32(RFC);
+ temp = er32(ROC);
+ temp = er32(RJC);
+ temp = er32(TORL);
+ temp = er32(TORH);
+ temp = er32(TOTL);
+ temp = er32(TOTH);
+ temp = er32(TPR);
+ temp = er32(TPT);
if (hw->mac_type != e1000_ich8lan) {
- temp = E1000_READ_REG(hw, PTC64);
- temp = E1000_READ_REG(hw, PTC127);
- temp = E1000_READ_REG(hw, PTC255);
- temp = E1000_READ_REG(hw, PTC511);
- temp = E1000_READ_REG(hw, PTC1023);
- temp = E1000_READ_REG(hw, PTC1522);
+ temp = er32(PTC64);
+ temp = er32(PTC127);
+ temp = er32(PTC255);
+ temp = er32(PTC511);
+ temp = er32(PTC1023);
+ temp = er32(PTC1522);
}
- temp = E1000_READ_REG(hw, MPTC);
- temp = E1000_READ_REG(hw, BPTC);
+ temp = er32(MPTC);
+ temp = er32(BPTC);
if (hw->mac_type < e1000_82543) return;
- temp = E1000_READ_REG(hw, ALGNERRC);
- temp = E1000_READ_REG(hw, RXERRC);
- temp = E1000_READ_REG(hw, TNCRS);
- temp = E1000_READ_REG(hw, CEXTERR);
- temp = E1000_READ_REG(hw, TSCTC);
- temp = E1000_READ_REG(hw, TSCTFC);
+ temp = er32(ALGNERRC);
+ temp = er32(RXERRC);
+ temp = er32(TNCRS);
+ temp = er32(CEXTERR);
+ temp = er32(TSCTC);
+ temp = er32(TSCTFC);
if (hw->mac_type <= e1000_82544) return;
- temp = E1000_READ_REG(hw, MGTPRC);
- temp = E1000_READ_REG(hw, MGTPDC);
- temp = E1000_READ_REG(hw, MGTPTC);
+ temp = er32(MGTPRC);
+ temp = er32(MGTPDC);
+ temp = er32(MGTPTC);
if (hw->mac_type <= e1000_82547_rev_2) return;
- temp = E1000_READ_REG(hw, IAC);
- temp = E1000_READ_REG(hw, ICRXOC);
+ temp = er32(IAC);
+ temp = er32(ICRXOC);
if (hw->mac_type == e1000_ich8lan) return;
- temp = E1000_READ_REG(hw, ICRXPTC);
- temp = E1000_READ_REG(hw, ICRXATC);
- temp = E1000_READ_REG(hw, ICTXPTC);
- temp = E1000_READ_REG(hw, ICTXATC);
- temp = E1000_READ_REG(hw, ICTXQEC);
- temp = E1000_READ_REG(hw, ICTXQMTC);
- temp = E1000_READ_REG(hw, ICRXDMTC);
+ temp = er32(ICRXPTC);
+ temp = er32(ICRXATC);
+ temp = er32(ICTXPTC);
+ temp = er32(ICTXATC);
+ temp = er32(ICTXQEC);
+ temp = er32(ICTXQMTC);
+ temp = er32(ICRXDMTC);
}
/******************************************************************************
@@ -6428,8 +6317,7 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
* current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
* before calling this function.
*****************************************************************************/
-void
-e1000_reset_adaptive(struct e1000_hw *hw)
+void e1000_reset_adaptive(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_reset_adaptive");
@@ -6442,7 +6330,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
hw->ifs_ratio = IFS_RATIO;
}
hw->in_ifs_mode = false;
- E1000_WRITE_REG(hw, AIT, 0);
+ ew32(AIT, 0);
} else {
DEBUGOUT("Not in Adaptive IFS mode!\n");
}
@@ -6456,8 +6344,7 @@ e1000_reset_adaptive(struct e1000_hw *hw)
* tx_packets - Number of transmits since last callback
* total_collisions - Number of collisions since last callback
*****************************************************************************/
-void
-e1000_update_adaptive(struct e1000_hw *hw)
+void e1000_update_adaptive(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_update_adaptive");
@@ -6470,14 +6357,14 @@ e1000_update_adaptive(struct e1000_hw *hw)
hw->current_ifs_val = hw->ifs_min_val;
else
hw->current_ifs_val += hw->ifs_step_size;
- E1000_WRITE_REG(hw, AIT, hw->current_ifs_val);
+ ew32(AIT, hw->current_ifs_val);
}
}
} else {
if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
hw->current_ifs_val = 0;
hw->in_ifs_mode = false;
- E1000_WRITE_REG(hw, AIT, 0);
+ ew32(AIT, 0);
}
}
} else {
@@ -6492,11 +6379,8 @@ e1000_update_adaptive(struct e1000_hw *hw)
* frame_len - The length of the frame in question
* mac_addr - The Ethernet destination address of the frame in question
*****************************************************************************/
-void
-e1000_tbi_adjust_stats(struct e1000_hw *hw,
- struct e1000_hw_stats *stats,
- u32 frame_len,
- u8 *mac_addr)
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
+ u32 frame_len, u8 *mac_addr)
{
u64 carry_bit;
@@ -6527,7 +6411,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
* since the test for a multicast frame will test positive on
* a broadcast frame.
*/
- if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+ if ((mac_addr[0] == (u8)0xff) && (mac_addr[1] == (u8)0xff))
/* Broadcast packet */
stats->bprc++;
else if (*mac_addr & 0x01)
@@ -6570,8 +6454,7 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
-e1000_get_bus_info(struct e1000_hw *hw)
+void e1000_get_bus_info(struct e1000_hw *hw)
{
s32 ret_val;
u16 pci_ex_link_status;
@@ -6605,7 +6488,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_width = e1000_bus_width_pciex_1;
break;
default:
- status = E1000_READ_REG(hw, STATUS);
+ status = er32(STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
e1000_bus_type_pcix : e1000_bus_type_pci;
@@ -6645,10 +6528,7 @@ e1000_get_bus_info(struct e1000_hw *hw)
* offset - offset to write to
* value - value to write
*****************************************************************************/
-static void
-e1000_write_reg_io(struct e1000_hw *hw,
- u32 offset,
- u32 value)
+static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
{
unsigned long io_addr = hw->io_base;
unsigned long io_data = hw->io_base + 4;
@@ -6672,10 +6552,8 @@ e1000_write_reg_io(struct e1000_hw *hw,
* register to the minimum and maximum range.
* For IGP phy's, the function calculates the range by the AGC registers.
*****************************************************************************/
-static s32
-e1000_get_cable_length(struct e1000_hw *hw,
- u16 *min_length,
- u16 *max_length)
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+ u16 *max_length)
{
s32 ret_val;
u16 agc_value = 0;
@@ -6863,9 +6741,8 @@ e1000_get_cable_length(struct e1000_hw *hw,
* return 0. If the link speed is 1000 Mbps the polarity status is in the
* IGP01E1000_PHY_PCS_INIT_REG.
*****************************************************************************/
-static s32
-e1000_check_polarity(struct e1000_hw *hw,
- e1000_rev_polarity *polarity)
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity)
{
s32 ret_val;
u16 phy_data;
@@ -6939,8 +6816,7 @@ e1000_check_polarity(struct e1000_hw *hw,
* Link Health register. In IGP this bit is latched high, so the driver must
* read it immediately after link is established.
*****************************************************************************/
-static s32
-e1000_check_downshift(struct e1000_hw *hw)
+static s32 e1000_check_downshift(struct e1000_hw *hw)
{
s32 ret_val;
u16 phy_data;
@@ -6985,9 +6861,7 @@ e1000_check_downshift(struct e1000_hw *hw)
*
****************************************************************************/
-static s32
-e1000_config_dsp_after_link_change(struct e1000_hw *hw,
- bool link_up)
+static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
{
s32 ret_val;
u16 phy_data, phy_saved_data, speed, duplex, i;
@@ -7173,8 +7047,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
****************************************************************************/
-static s32
-e1000_set_phy_mode(struct e1000_hw *hw)
+static s32 e1000_set_phy_mode(struct e1000_hw *hw)
{
s32 ret_val;
u16 eeprom_data;
@@ -7218,9 +7091,7 @@ e1000_set_phy_mode(struct e1000_hw *hw)
*
****************************************************************************/
-static s32
-e1000_set_d3_lplu_state(struct e1000_hw *hw,
- bool active)
+static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
{
u32 phy_ctrl = 0;
s32 ret_val;
@@ -7242,7 +7113,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
/* MAC writes into PHY register based on the state transition
* and start auto-negotiation. SW driver can overwrite the settings
* in CSR PHY power control E1000_PHY_CTRL register. */
- phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+ phy_ctrl = er32(PHY_CTRL);
} else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if (ret_val)
@@ -7259,7 +7130,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
} else {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data &= ~IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7310,7 +7181,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
} else {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data |= IGP02E1000_PM_D3_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7348,9 +7219,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
*
****************************************************************************/
-static s32
-e1000_set_d0_lplu_state(struct e1000_hw *hw,
- bool active)
+static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
{
u32 phy_ctrl = 0;
s32 ret_val;
@@ -7361,7 +7230,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
return E1000_SUCCESS;
if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+ phy_ctrl = er32(PHY_CTRL);
} else {
ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
if (ret_val)
@@ -7371,7 +7240,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
if (!active) {
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data &= ~IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7412,7 +7281,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
if (hw->mac_type == e1000_ich8lan) {
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
- E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+ ew32(PHY_CTRL, phy_ctrl);
} else {
phy_data |= IGP02E1000_PM_D0_LPLU;
ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7439,8 +7308,7 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_set_vco_speed(struct e1000_hw *hw)
+static s32 e1000_set_vco_speed(struct e1000_hw *hw)
{
s32 ret_val;
u16 default_page = 0;
@@ -7503,8 +7371,7 @@ e1000_set_vco_speed(struct e1000_hw *hw)
*
* returns: - E1000_SUCCESS .
****************************************************************************/
-static s32
-e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer)
{
u8 i;
u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
@@ -7514,7 +7381,7 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
offset = (offset >> 2);
for (i = 0; i < length; i++) {
- *((u32 *) buffer + i) =
+ *((u32 *)buffer + i) =
E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
}
return E1000_SUCCESS;
@@ -7530,21 +7397,20 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
* timeout
* - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_enable_host_if(struct e1000_hw * hw)
+static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
{
u32 hicr;
u8 i;
/* Check that the host interface is enabled. */
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
if ((hicr & E1000_HICR_EN) == 0) {
DEBUGOUT("E1000_HOST_EN bit disabled.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
/* check the previous command is completed */
for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
if (!(hicr & E1000_HICR_C))
break;
mdelay(1);
@@ -7564,9 +7430,8 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
- u16 length, u16 offset, u8 *sum)
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+ u16 offset, u8 *sum)
{
u8 *tmp;
u8 *bufptr = buffer;
@@ -7632,9 +7497,8 @@ e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_write_cmd_header(struct e1000_hw * hw,
- struct e1000_host_mng_command_header * hdr)
+static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+ struct e1000_host_mng_command_header *hdr)
{
u16 i;
u8 sum;
@@ -7648,7 +7512,7 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
sum = hdr->checksum;
hdr->checksum = 0;
- buffer = (u8 *) hdr;
+ buffer = (u8 *)hdr;
i = length;
while (i--)
sum += buffer[i];
@@ -7658,8 +7522,8 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
length >>= 2;
/* The device driver writes the relevant command block into the ram area. */
for (i = 0; i < length; i++) {
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *)hdr + i));
+ E1000_WRITE_FLUSH();
}
return E1000_SUCCESS;
@@ -7672,14 +7536,13 @@ e1000_mng_write_cmd_header(struct e1000_hw * hw,
*
* returns - E1000_SUCCESS for success.
****************************************************************************/
-static s32
-e1000_mng_write_commit(struct e1000_hw * hw)
+static s32 e1000_mng_write_commit(struct e1000_hw *hw)
{
u32 hicr;
- hicr = E1000_READ_REG(hw, HICR);
+ hicr = er32(HICR);
/* Setting this bit tells the ARC that a new command is pending. */
- E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C);
+ ew32(HICR, hicr | E1000_HICR_C);
return E1000_SUCCESS;
}
@@ -7690,12 +7553,11 @@ e1000_mng_write_commit(struct e1000_hw * hw)
*
* returns - true when the mode is IAMT or false.
****************************************************************************/
-bool
-e1000_check_mng_mode(struct e1000_hw *hw)
+bool e1000_check_mng_mode(struct e1000_hw *hw)
{
u32 fwsm;
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
if (hw->mac_type == e1000_ich8lan) {
if ((fwsm & E1000_FWSM_MODE_MASK) ==
@@ -7712,9 +7574,7 @@ e1000_check_mng_mode(struct e1000_hw *hw)
/*****************************************************************************
* This function writes the dhcp info .
****************************************************************************/
-s32
-e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
- u16 length)
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
{
s32 ret_val;
struct e1000_host_mng_command_header hdr;
@@ -7744,8 +7604,7 @@ e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
*
* returns - checksum of buffer contents.
****************************************************************************/
-static u8
-e1000_calculate_mng_checksum(char *buffer, u32 length)
+static u8 e1000_calculate_mng_checksum(char *buffer, u32 length)
{
u8 sum = 0;
u32 i;
@@ -7756,7 +7615,7 @@ e1000_calculate_mng_checksum(char *buffer, u32 length)
for (i=0; i < length; i++)
sum += buffer[i];
- return (u8) (0 - sum);
+ return (u8)(0 - sum);
}
/*****************************************************************************
@@ -7764,8 +7623,7 @@ e1000_calculate_mng_checksum(char *buffer, u32 length)
*
* returns - true for packet filtering or false.
****************************************************************************/
-bool
-e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
{
/* called in init as well as watchdog timer functions */
@@ -7806,21 +7664,20 @@ e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
* returns: - true/false
*
*****************************************************************************/
-u32
-e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
{
u32 manc;
u32 fwsm, factps;
if (hw->asf_firmware_present) {
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
if (!(manc & E1000_MANC_RCV_TCO_EN) ||
!(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
return false;
if (e1000_arc_subsystem_valid(hw)) {
- fwsm = E1000_READ_REG(hw, FWSM);
- factps = E1000_READ_REG(hw, FACTPS);
+ fwsm = er32(FWSM);
+ factps = er32(FACTPS);
if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
@@ -7832,8 +7689,7 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
return false;
}
-static s32
-e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
{
s32 ret_val;
u16 mii_status_reg;
@@ -7926,8 +7782,7 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
* returns: - none.
*
***************************************************************************/
-static void
-e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+static void e1000_set_pci_express_master_disable(struct e1000_hw *hw)
{
u32 ctrl;
@@ -7936,9 +7791,9 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
if (hw->bus_type != e1000_bus_type_pci_express)
return;
- ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
- E1000_WRITE_REG(hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
/*******************************************************************************
@@ -7952,8 +7807,7 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw)
* E1000_SUCCESS master requests disabled.
*
******************************************************************************/
-s32
-e1000_disable_pciex_master(struct e1000_hw *hw)
+s32 e1000_disable_pciex_master(struct e1000_hw *hw)
{
s32 timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
@@ -7965,7 +7819,7 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
e1000_set_pci_express_master_disable(hw);
while (timeout) {
- if (!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+ if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
break;
else
udelay(100);
@@ -7990,8 +7844,7 @@ e1000_disable_pciex_master(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
******************************************************************************/
-static s32
-e1000_get_auto_rd_done(struct e1000_hw *hw)
+static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
{
s32 timeout = AUTO_READ_DONE_TIMEOUT;
@@ -8007,7 +7860,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
case e1000_80003es2lan:
case e1000_ich8lan:
while (timeout) {
- if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
+ if (er32(EECD) & E1000_EECD_AUTO_RD)
break;
else msleep(1);
timeout--;
@@ -8038,8 +7891,7 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_phy_cfg_done(struct e1000_hw *hw)
+static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
u32 cfg_mask = E1000_EEPROM_CFG_DONE;
@@ -8052,13 +7904,13 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
break;
case e1000_80003es2lan:
/* Separate *_CFG_DONE_* bit for each port */
- if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
/* Fall Through */
case e1000_82571:
case e1000_82572:
while (timeout) {
- if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+ if (er32(EEMNGCTL) & cfg_mask)
break;
else
msleep(1);
@@ -8085,8 +7937,7 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
{
s32 timeout;
u32 swsm;
@@ -8105,11 +7956,11 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
/* Get the FW semaphore. */
timeout = hw->eeprom.word_size + 1;
while (timeout) {
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
swsm |= E1000_SWSM_SWESMBI;
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
/* if we managed to set the bit we got the semaphore. */
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
if (swsm & E1000_SWSM_SWESMBI)
break;
@@ -8135,8 +7986,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
* returns: - None.
*
***************************************************************************/
-static void
-e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
{
u32 swsm;
@@ -8145,13 +7995,13 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
if (!hw->eeprom_semaphore_present)
return;
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
if (hw->mac_type == e1000_80003es2lan) {
/* Release both semaphores. */
swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
} else
swsm &= ~(E1000_SWSM_SWESMBI);
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
}
/***************************************************************************
@@ -8164,8 +8014,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS at any other case.
*
***************************************************************************/
-static s32
-e1000_get_software_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_software_semaphore(struct e1000_hw *hw)
{
s32 timeout = hw->eeprom.word_size + 1;
u32 swsm;
@@ -8177,7 +8026,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
}
while (timeout) {
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
/* If SMBI bit cleared, it is now set and we hold the semaphore */
if (!(swsm & E1000_SWSM_SMBI))
break;
@@ -8200,8 +8049,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static void
-e1000_release_software_semaphore(struct e1000_hw *hw)
+static void e1000_release_software_semaphore(struct e1000_hw *hw)
{
u32 swsm;
@@ -8211,10 +8059,10 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
return;
}
- swsm = E1000_READ_REG(hw, SWSM);
+ swsm = er32(SWSM);
/* Release the SW semaphores.*/
swsm &= ~E1000_SWSM_SMBI;
- E1000_WRITE_REG(hw, SWSM, swsm);
+ ew32(SWSM, swsm);
}
/******************************************************************************
@@ -8228,26 +8076,24 @@ e1000_release_software_semaphore(struct e1000_hw *hw)
* E1000_SUCCESS
*
*****************************************************************************/
-s32
-e1000_check_phy_reset_block(struct e1000_hw *hw)
+s32 e1000_check_phy_reset_block(struct e1000_hw *hw)
{
u32 manc = 0;
u32 fwsm = 0;
if (hw->mac_type == e1000_ich8lan) {
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
: E1000_BLK_PHY_RESET;
}
if (hw->mac_type > e1000_82547_rev_2)
- manc = E1000_READ_REG(hw, MANC);
+ manc = er32(MANC);
return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
E1000_BLK_PHY_RESET : E1000_SUCCESS;
}
-static u8
-e1000_arc_subsystem_valid(struct e1000_hw *hw)
+static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw)
{
u32 fwsm;
@@ -8261,7 +8107,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
case e1000_82572:
case e1000_82573:
case e1000_80003es2lan:
- fwsm = E1000_READ_REG(hw, FWSM);
+ fwsm = er32(FWSM);
if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
return true;
break;
@@ -8283,8 +8129,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw)
* returns: E1000_SUCCESS
*
*****************************************************************************/
-static s32
-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
{
u32 gcr_reg = 0;
@@ -8297,19 +8142,19 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
return E1000_SUCCESS;
if (no_snoop) {
- gcr_reg = E1000_READ_REG(hw, GCR);
+ gcr_reg = er32(GCR);
gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL);
gcr_reg |= no_snoop;
- E1000_WRITE_REG(hw, GCR, gcr_reg);
+ ew32(GCR, gcr_reg);
}
if (hw->mac_type == e1000_ich8lan) {
u32 ctrl_ext;
- E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+ ew32(GCR, PCI_EX_82566_SNOOP_ALL);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
return E1000_SUCCESS;
@@ -8324,8 +8169,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static s32
-e1000_get_software_flag(struct e1000_hw *hw)
+static s32 e1000_get_software_flag(struct e1000_hw *hw)
{
s32 timeout = PHY_CFG_TIMEOUT;
u32 extcnf_ctrl;
@@ -8334,11 +8178,11 @@ e1000_get_software_flag(struct e1000_hw *hw)
if (hw->mac_type == e1000_ich8lan) {
while (timeout) {
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
- extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl = er32(EXTCNF_CTRL);
if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
break;
mdelay(1);
@@ -8363,17 +8207,16 @@ e1000_get_software_flag(struct e1000_hw *hw)
* hw: Struct containing variables accessed by shared code
*
***************************************************************************/
-static void
-e1000_release_software_flag(struct e1000_hw *hw)
+static void e1000_release_software_flag(struct e1000_hw *hw)
{
u32 extcnf_ctrl;
DEBUGFUNC("e1000_release_software_flag");
if (hw->mac_type == e1000_ich8lan) {
- extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl= er32(EXTCNF_CTRL);
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ ew32(EXTCNF_CTRL, extcnf_ctrl);
}
return;
@@ -8388,9 +8231,8 @@ e1000_release_software_flag(struct e1000_hw *hw)
* data - word read from the EEPROM
* words - number of words to read
*****************************************************************************/
-static s32
-e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
s32 error = E1000_SUCCESS;
u32 flash_bank = 0;
@@ -8405,7 +8247,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
* to be updated with each read.
*/
/* Value of bit 22 corresponds to the flash bank we're on. */
- flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
+ flash_bank = (er32(EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
/* Adjust offset appropriately if we're on bank 1 - adjust for word size */
bank_offset = flash_bank * (hw->flash_bank_size * 2);
@@ -8444,9 +8286,8 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
* words - number of words to write
* data - words to write to the EEPROM
*****************************************************************************/
-static s32
-e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
u32 i = 0;
s32 error = E1000_SUCCESS;
@@ -8491,8 +8332,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
*
* hw - The pointer to the hw structure
****************************************************************************/
-static s32
-e1000_ich8_cycle_init(struct e1000_hw *hw)
+static s32 e1000_ich8_cycle_init(struct e1000_hw *hw)
{
union ich8_hws_flash_status hsfsts;
s32 error = E1000_ERR_EEPROM;
@@ -8558,8 +8398,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw)
*
* hw - The pointer to the hw structure
****************************************************************************/
-static s32
-e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
{
union ich8_hws_flash_ctrl hsflctl;
union ich8_hws_flash_status hsfsts;
@@ -8593,9 +8432,8 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
* size - Size of data to read, 1=byte 2=word
* data - Pointer to the word to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
- u32 size, u16* data)
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 *data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8672,9 +8510,8 @@ e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
* size - Size of data to read, 1=byte 2=word
* data - The byte(s) to write to the NVM.
*****************************************************************************/
-static s32
-e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 data)
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+ u16 data)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8747,8 +8584,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
* index - The index of the byte to read.
* data - Pointer to a byte to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data)
{
s32 status = E1000_SUCCESS;
u16 word = 0;
@@ -8770,8 +8606,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
* index - The index of the byte to write.
* byte - The byte to write to the NVM.
*****************************************************************************/
-static s32
-e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
{
s32 error = E1000_SUCCESS;
s32 program_retries = 0;
@@ -8803,8 +8638,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
* index - The index of the byte to read.
* data - The byte to write to the NVM.
*****************************************************************************/
-static s32
-e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
{
s32 status = E1000_SUCCESS;
u16 word = (u16)data;
@@ -8821,8 +8655,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
* index - The starting byte index of the word to read.
* data - Pointer to a word to store the value read.
*****************************************************************************/
-static s32
-e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
{
s32 status = E1000_SUCCESS;
status = e1000_read_ich8_data(hw, index, 2, data);
@@ -8840,8 +8673,7 @@ e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
* amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
* bank size may be 4, 8 or 64 KBytes
*****************************************************************************/
-static s32
-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
{
union ich8_hws_flash_status hsfsts;
union ich8_hws_flash_ctrl hsflctl;
@@ -8930,9 +8762,9 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
return error;
}
-static s32
-e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
- u32 cnf_base_addr, u32 cnf_size)
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+ u32 cnf_base_addr,
+ u32 cnf_size)
{
u32 ret_val = E1000_SUCCESS;
u16 word_addr, reg_data, reg_addr;
@@ -8972,8 +8804,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
*
* hw: Struct containing variables accessed by shared code
*****************************************************************************/
-static s32
-e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
{
u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
@@ -8981,32 +8812,32 @@ e1000_init_lcd_from_nvm(struct e1000_hw *hw)
return E1000_SUCCESS;
/* Check if SW needs configure the PHY */
- reg_data = E1000_READ_REG(hw, FEXTNVM);
+ reg_data = er32(FEXTNVM);
if (!(reg_data & FEXTNVM_SW_CONFIG))
return E1000_SUCCESS;
/* Wait for basic configuration completes before proceeding*/
loop = 0;
do {
- reg_data = E1000_READ_REG(hw, STATUS) & E1000_STATUS_LAN_INIT_DONE;
+ reg_data = er32(STATUS) & E1000_STATUS_LAN_INIT_DONE;
udelay(100);
loop++;
} while ((!reg_data) && (loop < 50));
/* Clear the Init Done bit for the next init event */
- reg_data = E1000_READ_REG(hw, STATUS);
+ reg_data = er32(STATUS);
reg_data &= ~E1000_STATUS_LAN_INIT_DONE;
- E1000_WRITE_REG(hw, STATUS, reg_data);
+ ew32(STATUS, reg_data);
/* Make sure HW does not configure LCD from PHY extended configuration
before SW configuration */
- reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ reg_data = er32(EXTCNF_CTRL);
if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) {
- reg_data = E1000_READ_REG(hw, EXTCNF_SIZE);
+ reg_data = er32(EXTCNF_SIZE);
cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH;
cnf_size >>= 16;
if (cnf_size) {
- reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+ reg_data = er32(EXTCNF_CTRL);
cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER;
/* cnf_base_addr is in DWORD */
cnf_base_addr >>= 16;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index cf12b05cd01..ad6da7b67e5 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -31,12 +31,7 @@
char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#ifndef CONFIG_E1000_NAPI
-#define DRIVERNAPI
-#else
-#define DRIVERNAPI "-NAPI"
-#endif
-#define DRV_VERSION "7.3.20-k2"DRIVERNAPI
+#define DRV_VERSION "7.3.20-k3-NAPI"
const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -138,7 +133,6 @@ static irqreturn_t e1000_intr(int irq, void *data);
static irqreturn_t e1000_intr_msi(int irq, void *data);
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring);
-#ifdef CONFIG_E1000_NAPI
static int e1000_clean(struct napi_struct *napi, int budget);
static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
@@ -146,12 +140,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int *work_done, int work_to_do);
-#else
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
-#endif
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring,
int cleaned_count);
@@ -232,8 +220,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
* loaded. All it does is register with the PCI subsystem.
**/
-static int __init
-e1000_init_module(void)
+static int __init e1000_init_module(void)
{
int ret;
printk(KERN_INFO "%s - version %s\n",
@@ -261,8 +248,7 @@ module_init(e1000_init_module);
* from memory.
**/
-static void __exit
-e1000_exit_module(void)
+static void __exit e1000_exit_module(void)
{
pci_unregister_driver(&e1000_driver);
}
@@ -271,12 +257,13 @@ module_exit(e1000_exit_module);
static int e1000_request_irq(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
irq_handler_t handler = e1000_intr;
int irq_flags = IRQF_SHARED;
int err;
- if (adapter->hw.mac_type >= e1000_82571) {
+ if (hw->mac_type >= e1000_82571) {
adapter->have_msi = !pci_enable_msi(adapter->pdev);
if (adapter->have_msi) {
handler = e1000_intr_msi;
@@ -311,11 +298,12 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
* @adapter: board private structure
**/
-static void
-e1000_irq_disable(struct e1000_adapter *adapter)
+static void e1000_irq_disable(struct e1000_adapter *adapter)
{
- E1000_WRITE_REG(&adapter->hw, IMC, ~0);
- E1000_WRITE_FLUSH(&adapter->hw);
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32(IMC, ~0);
+ E1000_WRITE_FLUSH();
synchronize_irq(adapter->pdev->irq);
}
@@ -324,22 +312,23 @@ e1000_irq_disable(struct e1000_adapter *adapter)
* @adapter: board private structure
**/
-static void
-e1000_irq_enable(struct e1000_adapter *adapter)
+static void e1000_irq_enable(struct e1000_adapter *adapter)
{
- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
- E1000_WRITE_FLUSH(&adapter->hw);
+ struct e1000_hw *hw = &adapter->hw;
+
+ ew32(IMS, IMS_ENABLE_MASK);
+ E1000_WRITE_FLUSH();
}
-static void
-e1000_update_mng_vlan(struct e1000_adapter *adapter)
+static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- u16 vid = adapter->hw.mng_cookie.vlan_id;
+ u16 vid = hw->mng_cookie.vlan_id;
u16 old_vid = adapter->mng_vlan_id;
if (adapter->vlgrp) {
if (!vlan_group_get_device(adapter->vlgrp, vid)) {
- if (adapter->hw.mng_cookie.status &
+ if (hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
@@ -366,26 +355,24 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
*
**/
-static void
-e1000_release_hw_control(struct e1000_adapter *adapter)
+static void e1000_release_hw_control(struct e1000_adapter *adapter)
{
u32 ctrl_ext;
u32 swsm;
+ struct e1000_hw *hw = &adapter->hw;
/* Let firmware taken over control of h/w */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm & ~E1000_SWSM_DRV_LOAD);
+ swsm = er32(SWSM);
+ ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
break;
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case e1000_ich8lan:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ ctrl_ext = er32(CTRL_EXT);
+ ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
break;
default:
break;
@@ -403,37 +390,36 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
*
**/
-static void
-e1000_get_hw_control(struct e1000_adapter *adapter)
+static void e1000_get_hw_control(struct e1000_adapter *adapter)
{
u32 ctrl_ext;
u32 swsm;
+ struct e1000_hw *hw = &adapter->hw;
/* Let firmware know the driver has taken over */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm | E1000_SWSM_DRV_LOAD);
+ swsm = er32(SWSM);
+ ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
break;
case e1000_82571:
case e1000_82572:
case e1000_80003es2lan:
case e1000_ich8lan:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ ctrl_ext = er32(CTRL_EXT);
+ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
break;
default:
break;
}
}
-static void
-e1000_init_manageability(struct e1000_adapter *adapter)
+static void e1000_init_manageability(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
if (adapter->en_mng_pt) {
- u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ u32 manc = er32(MANC);
/* disable hardware interception of ARP */
manc &= ~(E1000_MANC_ARP_EN);
@@ -441,37 +427,38 @@ e1000_init_manageability(struct e1000_adapter *adapter)
/* enable receiving management packets to the host */
/* this will probably generate destination unreachable messages
* from the host OS, but the packets will be handled on SMBUS */
- if (adapter->hw.has_manc2h) {
- u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+ if (hw->has_manc2h) {
+ u32 manc2h = er32(MANC2H);
manc |= E1000_MANC_EN_MNG2HOST;
#define E1000_MNG2HOST_PORT_623 (1 << 5)
#define E1000_MNG2HOST_PORT_664 (1 << 6)
manc2h |= E1000_MNG2HOST_PORT_623;
manc2h |= E1000_MNG2HOST_PORT_664;
- E1000_WRITE_REG(&adapter->hw, MANC2H, manc2h);
+ ew32(MANC2H, manc2h);
}
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ ew32(MANC, manc);
}
}
-static void
-e1000_release_manageability(struct e1000_adapter *adapter)
+static void e1000_release_manageability(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
if (adapter->en_mng_pt) {
- u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+ u32 manc = er32(MANC);
/* re-enable hardware interception of ARP */
manc |= E1000_MANC_ARP_EN;
- if (adapter->hw.has_manc2h)
+ if (hw->has_manc2h)
manc &= ~E1000_MANC_EN_MNG2HOST;
/* don't explicitly have to mess with MANC2H since
* MANC has an enable disable that gates MANC2H */
- E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ ew32(MANC, manc);
}
}
@@ -506,18 +493,19 @@ static void e1000_configure(struct e1000_adapter *adapter)
int e1000_up(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* hardware has been reset, we need to reload some things */
e1000_configure(adapter);
clear_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_enable(&adapter->napi);
-#endif
+
e1000_irq_enable(adapter);
/* fire a link change interrupt to start the watchdog */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+ ew32(ICS, E1000_ICS_LSC);
return 0;
}
@@ -533,30 +521,33 @@ int e1000_up(struct e1000_adapter *adapter)
void e1000_power_up_phy(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 mii_reg = 0;
/* Just clear the power down bit to wake the phy back up */
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
/* according to the manual, the phy will retain its
* settings across a power-down/up cycle */
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
}
}
static void e1000_power_down_phy(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
+
/* Power down the PHY so no link is implied when interface is down *
* The PHY cannot be powered down if any of the following is true *
* (a) WoL is enabled
* (b) AMT is active
* (c) SoL/IDER session is active */
- if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
- adapter->hw.media_type == e1000_media_type_copper) {
+ if (!adapter->wol && hw->mac_type >= e1000_82540 &&
+ hw->media_type == e1000_media_type_copper) {
u16 mii_reg = 0;
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82540:
case e1000_82545:
case e1000_82545_rev_3:
@@ -566,8 +557,7 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
- if (E1000_READ_REG(&adapter->hw, MANC) &
- E1000_MANC_SMBUS_EN)
+ if (er32(MANC) & E1000_MANC_SMBUS_EN)
goto out;
break;
case e1000_82571:
@@ -575,24 +565,23 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter)
case e1000_82573:
case e1000_80003es2lan:
case e1000_ich8lan:
- if (e1000_check_mng_mode(&adapter->hw) ||
- e1000_check_phy_reset_block(&adapter->hw))
+ if (e1000_check_mng_mode(hw) ||
+ e1000_check_phy_reset_block(hw))
goto out;
break;
default:
goto out;
}
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
mdelay(1);
}
out:
return;
}
-void
-e1000_down(struct e1000_adapter *adapter)
+void e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -600,9 +589,8 @@ e1000_down(struct e1000_adapter *adapter)
* reschedule our watchdog timer */
set_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_disable(&adapter->napi);
-#endif
+
e1000_irq_disable(adapter);
del_timer_sync(&adapter->tx_fifo_stall_timer);
@@ -620,8 +608,7 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_rx_rings(adapter);
}
-void
-e1000_reinit_locked(struct e1000_adapter *adapter)
+void e1000_reinit_locked(struct e1000_adapter *adapter)
{
WARN_ON(in_interrupt());
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
@@ -631,9 +618,9 @@ e1000_reinit_locked(struct e1000_adapter *adapter)
clear_bit(__E1000_RESETTING, &adapter->flags);
}
-void
-e1000_reset(struct e1000_adapter *adapter)
+void e1000_reset(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 pba = 0, tx_space, min_tx_space, min_rx_space;
u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
bool legacy_pba_adjust = false;
@@ -642,7 +629,7 @@ e1000_reset(struct e1000_adapter *adapter)
* To take effect CTRL.RST is required.
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -683,16 +670,16 @@ e1000_reset(struct e1000_adapter *adapter)
if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
pba -= 8; /* allocate more FIFO for Tx */
- if (adapter->hw.mac_type == e1000_82547) {
+ if (hw->mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
- } else if (adapter->hw.max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
/* adjust PBA for jumbo frames */
- E1000_WRITE_REG(&adapter->hw, PBA, pba);
+ ew32(PBA, pba);
/* To maintain wire speed transmits, the Tx FIFO should be
* large enough to accomodate two full transmit packets,
@@ -700,7 +687,7 @@ e1000_reset(struct e1000_adapter *adapter)
* the Rx FIFO should be large enough to accomodate at least
* one full receive packet and is similarly rounded up and
* expressed in KB. */
- pba = E1000_READ_REG(&adapter->hw, PBA);
+ pba = er32(PBA);
/* upper 16 bits has Tx packet buffer allocation size in KB */
tx_space = pba >> 16;
/* lower 16 bits has Rx packet buffer allocation size in KB */
@@ -723,7 +710,7 @@ e1000_reset(struct e1000_adapter *adapter)
pba = pba - (min_tx_space - tx_space);
/* PCI/PCIx hardware has PBA alignment constraints */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82545 ... e1000_82546_rev_3:
pba &= ~(E1000_PBA_8K - 1);
break;
@@ -734,7 +721,7 @@ e1000_reset(struct e1000_adapter *adapter)
/* if short on rx space, rx wins and must trump tx
* adjustment or use Early Receive if available */
if (pba < min_rx_space) {
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82573:
/* ERT enabled in e1000_configure_rx */
break;
@@ -746,7 +733,7 @@ e1000_reset(struct e1000_adapter *adapter)
}
}
- E1000_WRITE_REG(&adapter->hw, PBA, pba);
+ ew32(PBA, pba);
/* flow control settings */
/* Set the FC high water mark to 90% of the FIFO size.
@@ -759,54 +746,54 @@ e1000_reset(struct e1000_adapter *adapter)
if (pba < E1000_PBA_16K)
fc_high_water_mark = (pba * 1024) - 1600;
- adapter->hw.fc_high_water = fc_high_water_mark;
- adapter->hw.fc_low_water = fc_high_water_mark - 8;
- if (adapter->hw.mac_type == e1000_80003es2lan)
- adapter->hw.fc_pause_time = 0xFFFF;
+ hw->fc_high_water = fc_high_water_mark;
+ hw->fc_low_water = fc_high_water_mark - 8;
+ if (hw->mac_type == e1000_80003es2lan)
+ hw->fc_pause_time = 0xFFFF;
else
- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
- adapter->hw.fc_send_xon = 1;
- adapter->hw.fc = adapter->hw.original_fc;
+ hw->fc_pause_time = E1000_FC_PAUSE_TIME;
+ hw->fc_send_xon = 1;
+ hw->fc = hw->original_fc;
/* Allow time for pending master requests to run */
- e1000_reset_hw(&adapter->hw);
- if (adapter->hw.mac_type >= e1000_82544)
- E1000_WRITE_REG(&adapter->hw, WUC, 0);
+ e1000_reset_hw(hw);
+ if (hw->mac_type >= e1000_82544)
+ ew32(WUC, 0);
- if (e1000_init_hw(&adapter->hw))
+ if (e1000_init_hw(hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
- if (adapter->hw.mac_type >= e1000_82544 &&
- adapter->hw.mac_type <= e1000_82547_rev_2 &&
- adapter->hw.autoneg == 1 &&
- adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
- u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ if (hw->mac_type >= e1000_82544 &&
+ hw->mac_type <= e1000_82547_rev_2 &&
+ hw->autoneg == 1 &&
+ hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+ u32 ctrl = er32(CTRL);
/* clear phy power management bit if we are in gig only mode,
* which if enabled will attempt negotiation to 100Mb, which
* can cause a loss of link at power off or driver unload */
ctrl &= ~E1000_CTRL_SWDPIN3;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
- E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+ ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
- e1000_reset_adaptive(&adapter->hw);
- e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ e1000_reset_adaptive(hw);
+ e1000_phy_get_info(hw, &adapter->phy_info);
if (!adapter->smart_power_down &&
- (adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572)) {
+ (hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572)) {
u16 phy_data = 0;
/* speed up time to link by disabling smart power down, ignore
* the return value of this function because there is nothing
* different we would do if it failed */
- e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
&phy_data);
phy_data &= ~IGP02E1000_PM_SPD;
- e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+ e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
phy_data);
}
@@ -865,13 +852,49 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter)
printk(KERN_ERR "to enable this network device.\n");
printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
"to your hardware vendor\n");
- printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n");
+ printk(KERN_ERR "or Intel Customer Support.\n");
printk(KERN_ERR "/*********************/\n");
kfree(data);
}
/**
+ * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
+ * @pdev: PCI device information struct
+ *
+ * Return true if an adapter needs ioport resources
+ **/
+static int e1000_is_need_ioport(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case E1000_DEV_ID_82540EM:
+ case E1000_DEV_ID_82540EM_LOM:
+ case E1000_DEV_ID_82540EP:
+ case E1000_DEV_ID_82540EP_LOM:
+ case E1000_DEV_ID_82540EP_LP:
+ case E1000_DEV_ID_82541EI:
+ case E1000_DEV_ID_82541EI_MOBILE:
+ case E1000_DEV_ID_82541ER:
+ case E1000_DEV_ID_82541ER_LOM:
+ case E1000_DEV_ID_82541GI:
+ case E1000_DEV_ID_82541GI_LF:
+ case E1000_DEV_ID_82541GI_MOBILE:
+ case E1000_DEV_ID_82544EI_COPPER:
+ case E1000_DEV_ID_82544EI_FIBER:
+ case E1000_DEV_ID_82544GC_COPPER:
+ case E1000_DEV_ID_82544GC_LOM:
+ case E1000_DEV_ID_82545EM_COPPER:
+ case E1000_DEV_ID_82545EM_FIBER:
+ case E1000_DEV_ID_82546EB_COPPER:
+ case E1000_DEV_ID_82546EB_FIBER:
+ case E1000_DEV_ID_82546EB_QUAD_COPPER:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
* @ent: entry in e1000_pci_tbl
@@ -882,37 +905,51 @@ static void e1000_dump_eeprom(struct e1000_adapter *adapter)
* The OS initialization, configuring of the adapter private structure,
* and a hardware reset occur.
**/
-
-static int __devinit
-e1000_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit e1000_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *netdev;
struct e1000_adapter *adapter;
+ struct e1000_hw *hw;
static int cards_found = 0;
static int global_quad_port_a = 0; /* global ksp3 port a indication */
int i, err, pci_using_dac;
u16 eeprom_data = 0;
u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ int bars, need_ioport;
DECLARE_MAC_BUF(mac);
- if ((err = pci_enable_device(pdev)))
+ /* do not allocate ioport bars when not needed */
+ need_ioport = e1000_is_need_ioport(pdev);
+ if (need_ioport) {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+ err = pci_enable_device(pdev);
+ } else {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ err = pci_enable_device(pdev);
+ }
+ if (err)
return err;
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
- !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
pci_using_dac = 1;
} else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
- (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
- E1000_ERR("No usable DMA configuration, aborting\n");
- goto err_dma;
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ E1000_ERR("No usable DMA configuration, "
+ "aborting\n");
+ goto err_dma;
+ }
}
pci_using_dac = 0;
}
- if ((err = pci_request_regions(pdev, e1000_driver_name)))
+ err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+ if (err)
goto err_pci_reg;
pci_set_master(pdev);
@@ -928,21 +965,27 @@ e1000_probe(struct pci_dev *pdev,
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
- adapter->hw.back = adapter;
adapter->msg_enable = (1 << debug) - 1;
+ adapter->bars = bars;
+ adapter->need_ioport = need_ioport;
+
+ hw = &adapter->hw;
+ hw->back = adapter;
err = -EIO;
- adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
- pci_resource_len(pdev, BAR_0));
- if (!adapter->hw.hw_addr)
+ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
+ pci_resource_len(pdev, BAR_0));
+ if (!hw->hw_addr)
goto err_ioremap;
- for (i = BAR_1; i <= BAR_5; i++) {
- if (pci_resource_len(pdev, i) == 0)
- continue;
- if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
- adapter->hw.io_base = pci_resource_start(pdev, i);
- break;
+ if (adapter->need_ioport) {
+ for (i = BAR_1; i <= BAR_5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
+ continue;
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ hw->io_base = pci_resource_start(pdev, i);
+ break;
+ }
}
}
@@ -957,9 +1000,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_set_ethtool_ops(netdev);
netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
-#ifdef CONFIG_E1000_NAPI
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
-#endif
netdev->vlan_rx_register = e1000_vlan_rx_register;
netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
@@ -972,49 +1013,50 @@ e1000_probe(struct pci_dev *pdev,
/* setup the private structure */
- if ((err = e1000_sw_init(adapter)))
+ err = e1000_sw_init(adapter);
+ if (err)
goto err_sw_init;
err = -EIO;
/* Flash BAR mapping must happen after e1000_sw_init
* because it depends on mac_type */
- if ((adapter->hw.mac_type == e1000_ich8lan) &&
+ if ((hw->mac_type == e1000_ich8lan) &&
(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
- adapter->hw.flash_address =
+ hw->flash_address =
ioremap(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
- if (!adapter->hw.flash_address)
+ if (!hw->flash_address)
goto err_flashmap;
}
- if (e1000_check_phy_reset_block(&adapter->hw))
+ if (e1000_check_phy_reset_block(hw))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
- if (adapter->hw.mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (adapter->hw.mac_type == e1000_ich8lan)
+ if (hw->mac_type == e1000_ich8lan)
netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
}
- if ((adapter->hw.mac_type >= e1000_82544) &&
- (adapter->hw.mac_type != e1000_82547))
+ if ((hw->mac_type >= e1000_82544) &&
+ (hw->mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
- if (adapter->hw.mac_type > e1000_82547_rev_2)
+ if (hw->mac_type > e1000_82547_rev_2)
netdev->features |= NETIF_F_TSO6;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
netdev->features |= NETIF_F_LLTX;
- adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+ adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
/* initialize eeprom parameters */
- if (e1000_init_eeprom_params(&adapter->hw)) {
+ if (e1000_init_eeprom_params(hw)) {
E1000_ERR("EEPROM initialization failed\n");
goto err_eeprom;
}
@@ -1022,10 +1064,10 @@ e1000_probe(struct pci_dev *pdev,
/* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
- e1000_reset_hw(&adapter->hw);
+ e1000_reset_hw(hw);
/* make sure the EEPROM is good */
- if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_eeprom_checksum(hw) < 0) {
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
e1000_dump_eeprom(adapter);
/*
@@ -1036,24 +1078,24 @@ e1000_probe(struct pci_dev *pdev,
* interface after manually setting a hw addr using
* `ip set address`
*/
- memset(adapter->hw.mac_addr, 0, netdev->addr_len);
+ memset(hw->mac_addr, 0, netdev->addr_len);
} else {
/* copy the MAC address out of the EEPROM */
- if (e1000_read_mac_addr(&adapter->hw))
+ if (e1000_read_mac_addr(hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
}
/* don't block initalization here due to bad MAC address */
- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
- memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->perm_addr))
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
- e1000_get_bus_info(&adapter->hw);
+ e1000_get_bus_info(hw);
init_timer(&adapter->tx_fifo_stall_timer);
adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter;
+ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &e1000_watchdog;
@@ -1061,7 +1103,7 @@ e1000_probe(struct pci_dev *pdev,
init_timer(&adapter->phy_info_timer);
adapter->phy_info_timer.function = &e1000_update_phy_info;
- adapter->phy_info_timer.data = (unsigned long) adapter;
+ adapter->phy_info_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, e1000_reset_task);
@@ -1072,18 +1114,18 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter
*/
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
break;
case e1000_82544:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_82544_APM;
break;
case e1000_ich8lan:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
break;
@@ -1091,14 +1133,14 @@ e1000_probe(struct pci_dev *pdev,
case e1000_82546_rev_3:
case e1000_82571:
case e1000_80003es2lan:
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
- e1000_read_eeprom(&adapter->hw,
+ if (er32(STATUS) & E1000_STATUS_FUNC_1){
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
}
/* Fall Through */
default:
- e1000_read_eeprom(&adapter->hw,
+ e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
@@ -1117,7 +1159,7 @@ e1000_probe(struct pci_dev *pdev,
case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber
* regardless of eeprom setting */
- if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
@@ -1140,8 +1182,6 @@ e1000_probe(struct pci_dev *pdev,
adapter->wol = adapter->eeprom_wol;
/* print bus type/speed/width info */
- {
- struct e1000_hw *hw = &adapter->hw;
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
(hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
@@ -1154,11 +1194,10 @@ e1000_probe(struct pci_dev *pdev,
(hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
(hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
"32-bit"));
- }
printk("%s\n", print_mac(mac, netdev->dev_addr));
- if (adapter->hw.bus_type == e1000_bus_type_pci_express) {
+ if (hw->bus_type == e1000_bus_type_pci_express) {
DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
"longer be supported by this driver in the future.\n",
pdev->vendor, pdev->device);
@@ -1173,8 +1212,8 @@ e1000_probe(struct pci_dev *pdev,
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
/* tell the stack to leave us alone until e1000_open() is called */
@@ -1182,7 +1221,8 @@ e1000_probe(struct pci_dev *pdev,
netif_stop_queue(netdev);
strcpy(netdev->name, "eth%d");
- if ((err = register_netdev(netdev)))
+ err = register_netdev(netdev);
+ if (err)
goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -1193,28 +1233,24 @@ e1000_probe(struct pci_dev *pdev,
err_register:
e1000_release_hw_control(adapter);
err_eeprom:
- if (!e1000_check_phy_reset_block(&adapter->hw))
- e1000_phy_hw_reset(&adapter->hw);
+ if (!e1000_check_phy_reset_block(hw))
+ e1000_phy_hw_reset(hw);
- if (adapter->hw.flash_address)
- iounmap(adapter->hw.flash_address);
+ if (hw->flash_address)
+ iounmap(hw->flash_address);
err_flashmap:
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++)
dev_put(&adapter->polling_netdev[i]);
-#endif
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
kfree(adapter->polling_netdev);
-#endif
err_sw_init:
- iounmap(adapter->hw.hw_addr);
+ iounmap(hw->hw_addr);
err_ioremap:
free_netdev(netdev);
err_alloc_etherdev:
- pci_release_regions(pdev);
+ pci_release_selected_regions(pdev, bars);
err_pci_reg:
err_dma:
pci_disable_device(pdev);
@@ -1231,14 +1267,12 @@ err_dma:
* memory.
**/
-static void __devexit
-e1000_remove(struct pci_dev *pdev)
+static void __devexit e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_E1000_NAPI
+ struct e1000_hw *hw = &adapter->hw;
int i;
-#endif
cancel_work_sync(&adapter->reset_task);
@@ -1248,26 +1282,22 @@ e1000_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. */
e1000_release_hw_control(adapter);
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++)
dev_put(&adapter->polling_netdev[i]);
-#endif
unregister_netdev(netdev);
- if (!e1000_check_phy_reset_block(&adapter->hw))
- e1000_phy_hw_reset(&adapter->hw);
+ if (!e1000_check_phy_reset_block(hw))
+ e1000_phy_hw_reset(hw);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
kfree(adapter->polling_netdev);
-#endif
- iounmap(adapter->hw.hw_addr);
- if (adapter->hw.flash_address)
- iounmap(adapter->hw.flash_address);
- pci_release_regions(pdev);
+ iounmap(hw->hw_addr);
+ if (hw->flash_address)
+ iounmap(hw->flash_address);
+ pci_release_selected_regions(pdev, adapter->bars);
free_netdev(netdev);
@@ -1283,15 +1313,12 @@ e1000_remove(struct pci_dev *pdev)
* OS network device settings (MTU size).
**/
-static int __devinit
-e1000_sw_init(struct e1000_adapter *adapter)
+static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
-#ifdef CONFIG_E1000_NAPI
int i;
-#endif
/* PCI config space info */
@@ -1349,14 +1376,12 @@ e1000_sw_init(struct e1000_adapter *adapter)
return -ENOMEM;
}
-#ifdef CONFIG_E1000_NAPI
for (i = 0; i < adapter->num_rx_queues; i++) {
adapter->polling_netdev[i].priv = adapter;
dev_hold(&adapter->polling_netdev[i]);
set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
}
spin_lock_init(&adapter->tx_queue_lock);
-#endif
/* Explicitly disable IRQ since the NIC can be in any state. */
e1000_irq_disable(adapter);
@@ -1377,8 +1402,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
* intended for Multiqueue, but should work fine with a single queue.
**/
-static int __devinit
-e1000_alloc_queues(struct e1000_adapter *adapter)
+static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
{
adapter->tx_ring = kcalloc(adapter->num_tx_queues,
sizeof(struct e1000_tx_ring), GFP_KERNEL);
@@ -1392,7 +1416,6 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
return -ENOMEM;
}
-#ifdef CONFIG_E1000_NAPI
adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
sizeof(struct net_device),
GFP_KERNEL);
@@ -1401,7 +1424,6 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
kfree(adapter->rx_ring);
return -ENOMEM;
}
-#endif
return E1000_SUCCESS;
}
@@ -1419,10 +1441,10 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
* and the stack is notified that the interface is ready.
**/
-static int
-e1000_open(struct net_device *netdev)
+static int e1000_open(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
int err;
/* disallow open during test */
@@ -1442,15 +1464,15 @@ e1000_open(struct net_device *netdev)
e1000_power_up_phy(adapter);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_update_mng_vlan(adapter);
}
/* If AMT is enabled, let the firmware know that the network
* interface is now open */
- if (adapter->hw.mac_type == e1000_82573 &&
- e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type == e1000_82573 &&
+ e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
/* before we allocate an interrupt, we must be ready to handle it.
@@ -1466,16 +1488,14 @@ e1000_open(struct net_device *netdev)
/* From here on the code is the same as e1000_up() */
clear_bit(__E1000_DOWN, &adapter->flags);
-#ifdef CONFIG_E1000_NAPI
napi_enable(&adapter->napi);
-#endif
e1000_irq_enable(adapter);
netif_start_queue(netdev);
/* fire a link status change interrupt to start the watchdog */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+ ew32(ICS, E1000_ICS_LSC);
return E1000_SUCCESS;
@@ -1503,10 +1523,10 @@ err_setup_tx:
* hardware, and all transmit and receive resources are freed.
**/
-static int
-e1000_close(struct net_device *netdev)
+static int e1000_close(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
e1000_down(adapter);
@@ -1518,7 +1538,7 @@ e1000_close(struct net_device *netdev)
/* kill manageability vlan ID if supported, but not if a vlan with
* the same ID is registered on the host OS (let 8021q kill it) */
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
!(adapter->vlgrp &&
vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
@@ -1527,8 +1547,8 @@ e1000_close(struct net_device *netdev)
/* If AMT is enabled, let the firmware know that the network
* interface is now closed */
- if (adapter->hw.mac_type == e1000_82573 &&
- e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type == e1000_82573 &&
+ e1000_check_mng_mode(hw))
e1000_release_hw_control(adapter);
return 0;
@@ -1540,17 +1560,17 @@ e1000_close(struct net_device *netdev)
* @start: address of beginning of memory
* @len: length of memory
**/
-static bool
-e1000_check_64k_bound(struct e1000_adapter *adapter,
- void *start, unsigned long len)
+static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
+ unsigned long len)
{
- unsigned long begin = (unsigned long) start;
+ struct e1000_hw *hw = &adapter->hw;
+ unsigned long begin = (unsigned long)start;
unsigned long end = begin + len;
/* First rev 82545 and 82546 need to not allow any memory
* write location to cross 64k boundary due to errata 23 */
- if (adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546) {
+ if (hw->mac_type == e1000_82545 ||
+ hw->mac_type == e1000_82546) {
return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
}
@@ -1565,9 +1585,8 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
* Return 0 on success, negative on failure
**/
-static int
-e1000_setup_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *txdr)
+static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *txdr)
{
struct pci_dev *pdev = adapter->pdev;
int size;
@@ -1641,8 +1660,7 @@ setup_tx_desc_die:
* Return 0 on success, negative on failure
**/
-int
-e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
@@ -1668,8 +1686,7 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
* Configure the Tx unit of the MAC after a reset.
**/
-static void
-e1000_configure_tx(struct e1000_adapter *adapter)
+static void e1000_configure_tx(struct e1000_adapter *adapter)
{
u64 tdba;
struct e1000_hw *hw = &adapter->hw;
@@ -1684,18 +1701,18 @@ e1000_configure_tx(struct e1000_adapter *adapter)
tdba = adapter->tx_ring[0].dma;
tdlen = adapter->tx_ring[0].count *
sizeof(struct e1000_tx_desc);
- E1000_WRITE_REG(hw, TDLEN, tdlen);
- E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, TDT, 0);
- E1000_WRITE_REG(hw, TDH, 0);
+ ew32(TDLEN, tdlen);
+ ew32(TDBAH, (tdba >> 32));
+ ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
+ ew32(TDT, 0);
+ ew32(TDH, 0);
adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
break;
}
/* Set the default values for the Tx Inter Packet Gap timer */
- if (adapter->hw.mac_type <= e1000_82547_rev_2 &&
+ if (hw->mac_type <= e1000_82547_rev_2 &&
(hw->media_type == e1000_media_type_fiber ||
hw->media_type == e1000_media_type_internal_serdes))
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
@@ -1720,34 +1737,34 @@ e1000_configure_tx(struct e1000_adapter *adapter)
}
tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
- E1000_WRITE_REG(hw, TIPG, tipg);
+ ew32(TIPG, tipg);
/* Set the Tx Interrupt Delay register */
- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+ ew32(TIDV, adapter->tx_int_delay);
if (hw->mac_type >= e1000_82540)
- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
+ ew32(TADV, adapter->tx_abs_int_delay);
/* Program the Transmit Control Register */
- tctl = E1000_READ_REG(hw, TCTL);
+ tctl = er32(TCTL);
tctl &= ~E1000_TCTL_CT;
tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
- tarc = E1000_READ_REG(hw, TARC0);
+ tarc = er32(TARC0);
/* set the speed mode bit, we'll clear it if we're not at
* gigabit link later */
tarc |= (1 << 21);
- E1000_WRITE_REG(hw, TARC0, tarc);
+ ew32(TARC0, tarc);
} else if (hw->mac_type == e1000_80003es2lan) {
- tarc = E1000_READ_REG(hw, TARC0);
+ tarc = er32(TARC0);
tarc |= 1;
- E1000_WRITE_REG(hw, TARC0, tarc);
- tarc = E1000_READ_REG(hw, TARC1);
+ ew32(TARC0, tarc);
+ tarc = er32(TARC1);
tarc |= 1;
- E1000_WRITE_REG(hw, TARC1, tarc);
+ ew32(TARC1, tarc);
}
e1000_config_collision_dist(hw);
@@ -1770,7 +1787,7 @@ e1000_configure_tx(struct e1000_adapter *adapter)
hw->bus_type == e1000_bus_type_pcix)
adapter->pcix_82544 = 1;
- E1000_WRITE_REG(hw, TCTL, tctl);
+ ew32(TCTL, tctl);
}
@@ -1782,10 +1799,10 @@ e1000_configure_tx(struct e1000_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_setup_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rxdr)
+static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rxdr)
{
+ struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
@@ -1818,7 +1835,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
return -ENOMEM;
}
- if (adapter->hw.mac_type <= e1000_82547_rev_2)
+ if (hw->mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1887,8 +1904,7 @@ setup_rx_desc_die:
* Return 0 on success, negative on failure
**/
-int
-e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
@@ -1913,24 +1929,24 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
**/
#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
(((S) & (PAGE_SIZE - 1)) ? 1 : 0))
-static void
-e1000_setup_rctl(struct e1000_adapter *adapter)
+static void e1000_setup_rctl(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u32 rctl, rfctl;
u32 psrctl = 0;
#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
u32 pages = 0;
#endif
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
- if (adapter->hw.tbi_compatibility_on == 1)
+ if (hw->tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
rctl &= ~E1000_RCTL_SBP;
@@ -1983,7 +1999,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
/* allocations using alloc_page take too long for regular MTU
* so only enable packet split for jumbo frames */
pages = PAGE_USE_COUNT(adapter->netdev->mtu);
- if ((adapter->hw.mac_type >= e1000_82571) && (pages <= 3) &&
+ if ((hw->mac_type >= e1000_82571) && (pages <= 3) &&
PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE))
adapter->rx_ps_pages = pages;
else
@@ -1991,14 +2007,14 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
#endif
if (adapter->rx_ps_pages) {
/* Configure extra packet-split registers */
- rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+ rfctl = er32(RFCTL);
rfctl |= E1000_RFCTL_EXTEN;
/* disable packet split support for IPv6 extension headers,
* because some malformed IPv6 headers can hang the RX */
rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
E1000_RFCTL_NEW_IPV6_EXT_DIS);
- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+ ew32(RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS;
@@ -2018,10 +2034,10 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
break;
}
- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
+ ew32(PSRCTL, psrctl);
}
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
/**
@@ -2031,8 +2047,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
* Configure the Rx unit of the MAC after a reset.
**/
-static void
-e1000_configure_rx(struct e1000_adapter *adapter)
+static void e1000_configure_rx(struct e1000_adapter *adapter)
{
u64 rdba;
struct e1000_hw *hw = &adapter->hw;
@@ -2052,30 +2067,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
}
/* disable receives while setting up the descriptors */
- rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
/* set the Receive Delay Timer Register */
- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+ ew32(RDTR, adapter->rx_int_delay);
if (hw->mac_type >= e1000_82540) {
- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
+ ew32(RADV, adapter->rx_abs_int_delay);
if (adapter->itr_setting != 0)
- E1000_WRITE_REG(hw, ITR,
- 1000000000 / (adapter->itr * 256));
+ ew32(ITR, 1000000000 / (adapter->itr * 256));
}
if (hw->mac_type >= e1000_82571) {
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
/* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
-#ifdef CONFIG_E1000_NAPI
/* Auto-Mask interrupts upon ICR access */
ctrl_ext |= E1000_CTRL_EXT_IAME;
- E1000_WRITE_REG(hw, IAM, 0xffffffff);
-#endif
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ ew32(IAM, 0xffffffff);
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
}
/* Setup the HW Rx Head and Tail Descriptor Pointers and
@@ -2084,11 +2096,11 @@ e1000_configure_rx(struct e1000_adapter *adapter)
case 1:
default:
rdba = adapter->rx_ring[0].dma;
- E1000_WRITE_REG(hw, RDLEN, rdlen);
- E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
- E1000_WRITE_REG(hw, RDT, 0);
- E1000_WRITE_REG(hw, RDH, 0);
+ ew32(RDLEN, rdlen);
+ ew32(RDBAH, (rdba >> 32));
+ ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
+ ew32(RDT, 0);
+ ew32(RDH, 0);
adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
break;
@@ -2096,7 +2108,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
- rxcsum = E1000_READ_REG(hw, RXCSUM);
+ rxcsum = er32(RXCSUM);
if (adapter->rx_csum) {
rxcsum |= E1000_RXCSUM_TUOFL;
@@ -2110,17 +2122,17 @@ e1000_configure_rx(struct e1000_adapter *adapter)
rxcsum &= ~E1000_RXCSUM_TUOFL;
/* don't need to clear IPPCSE as it defaults to 0 */
}
- E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+ ew32(RXCSUM, rxcsum);
}
/* enable early receives on 82573, only takes effect if using > 2048
* byte total frame size. for example only for jumbo frames */
#define E1000_ERT_2048 0x100
if (hw->mac_type == e1000_82573)
- E1000_WRITE_REG(hw, ERT, E1000_ERT_2048);
+ ew32(ERT, E1000_ERT_2048);
/* Enable Receives */
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
/**
@@ -2131,9 +2143,8 @@ e1000_configure_rx(struct e1000_adapter *adapter)
* Free all transmit software resources
**/
-static void
-e1000_free_tx_resources(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static void e1000_free_tx_resources(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2154,8 +2165,7 @@ e1000_free_tx_resources(struct e1000_adapter *adapter,
* Free all transmit software resources
**/
-void
-e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
{
int i;
@@ -2163,9 +2173,8 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
-static void
-e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
- struct e1000_buffer *buffer_info)
+static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
+ struct e1000_buffer *buffer_info)
{
if (buffer_info->dma) {
pci_unmap_page(adapter->pdev,
@@ -2187,10 +2196,10 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
* @tx_ring: ring to be cleaned
**/
-static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
unsigned long size;
unsigned int i;
@@ -2213,8 +2222,8 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
tx_ring->next_to_clean = 0;
tx_ring->last_tx_tso = 0;
- writel(0, adapter->hw.hw_addr + tx_ring->tdh);
- writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+ writel(0, hw->hw_addr + tx_ring->tdh);
+ writel(0, hw->hw_addr + tx_ring->tdt);
}
/**
@@ -2222,8 +2231,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
* @adapter: board private structure
**/
-static void
-e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
{
int i;
@@ -2239,9 +2247,8 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
* Free all receive software resources
**/
-static void
-e1000_free_rx_resources(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+static void e1000_free_rx_resources(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
struct pci_dev *pdev = adapter->pdev;
@@ -2266,8 +2273,7 @@ e1000_free_rx_resources(struct e1000_adapter *adapter,
* Free all receive software resources
**/
-void
-e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
{
int i;
@@ -2281,10 +2287,10 @@ e1000_free_all_rx_resources(struct e1000_adapter *adapter)
* @rx_ring: ring to free buffers from
**/
-static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
@@ -2331,8 +2337,8 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
- writel(0, adapter->hw.hw_addr + rx_ring->rdh);
- writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(0, hw->hw_addr + rx_ring->rdh);
+ writel(0, hw->hw_addr + rx_ring->rdt);
}
/**
@@ -2340,8 +2346,7 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
* @adapter: board private structure
**/
-static void
-e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
{
int i;
@@ -2352,38 +2357,38 @@ e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
* and memory write and invalidate disabled for certain operations
*/
-static void
-e1000_enter_82542_rst(struct e1000_adapter *adapter)
+static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 rctl;
- e1000_pci_clear_mwi(&adapter->hw);
+ e1000_pci_clear_mwi(hw);
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ ew32(RCTL, rctl);
+ E1000_WRITE_FLUSH();
mdelay(5);
if (netif_running(netdev))
e1000_clean_all_rx_rings(adapter);
}
-static void
-e1000_leave_82542_rst(struct e1000_adapter *adapter)
+static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 rctl;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_RST;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ ew32(RCTL, rctl);
+ E1000_WRITE_FLUSH();
mdelay(5);
- if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
- e1000_pci_set_mwi(&adapter->hw);
+ if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ e1000_pci_set_mwi(hw);
if (netif_running(netdev)) {
/* No need to loop, because 82542 supports only 1 queue */
@@ -2401,10 +2406,10 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_set_mac(struct net_device *netdev, void *p)
+static int e1000_set_mac(struct net_device *netdev, void *p)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
@@ -2412,19 +2417,19 @@ e1000_set_mac(struct net_device *netdev, void *p)
/* 82542 2.0 needs to be in reset to write receive address registers */
- if (adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+ memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ e1000_rar_set(hw, hw->mac_addr, 0);
/* With 82571 controllers, LAA may be overwritten (with the default)
* due to controller reset from the other port. */
- if (adapter->hw.mac_type == e1000_82571) {
+ if (hw->mac_type == e1000_82571) {
/* activate the work around */
- adapter->hw.laa_is_present = 1;
+ hw->laa_is_present = 1;
/* Hold a copy of the LAA in RAR[14] This is done so that
* between the time RAR[0] gets clobbered and the time it
@@ -2432,11 +2437,11 @@ e1000_set_mac(struct net_device *netdev, void *p)
* of the RARs and no incoming packets directed to this port
* are dropped. Eventaully the LAA will be in RAR[0] and
* RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ e1000_rar_set(hw, hw->mac_addr,
E1000_RAR_ENTRIES - 1);
}
- if (adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
return 0;
@@ -2452,8 +2457,7 @@ e1000_set_mac(struct net_device *netdev, void *p)
* promiscuous mode, and all-multi behavior.
**/
-static void
-e1000_set_rx_mode(struct net_device *netdev)
+static void e1000_set_rx_mode(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
@@ -2466,16 +2470,16 @@ e1000_set_rx_mode(struct net_device *netdev)
E1000_NUM_MTA_REGISTERS_ICH8LAN :
E1000_NUM_MTA_REGISTERS;
- if (adapter->hw.mac_type == e1000_ich8lan)
+ if (hw->mac_type == e1000_ich8lan)
rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
/* reserve RAR[14] for LAA over-write work-around */
- if (adapter->hw.mac_type == e1000_82571)
+ if (hw->mac_type == e1000_82571)
rar_entries--;
/* Check for Promiscuous and All Multicast modes */
- rctl = E1000_READ_REG(hw, RCTL);
+ rctl = er32(RCTL);
if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
@@ -2498,7 +2502,7 @@ e1000_set_rx_mode(struct net_device *netdev)
uc_ptr = netdev->uc_list;
}
- E1000_WRITE_REG(hw, RCTL, rctl);
+ ew32(RCTL, rctl);
/* 82542 2.0 needs to be in reset to write receive address registers */
@@ -2524,9 +2528,9 @@ e1000_set_rx_mode(struct net_device *netdev)
mc_ptr = mc_ptr->next;
} else {
E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
}
WARN_ON(uc_ptr != NULL);
@@ -2535,7 +2539,7 @@ e1000_set_rx_mode(struct net_device *netdev)
for (i = 0; i < mta_reg_count; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
- E1000_WRITE_FLUSH(hw);
+ E1000_WRITE_FLUSH();
}
/* load any remaining addresses into the hash table */
@@ -2552,11 +2556,11 @@ e1000_set_rx_mode(struct net_device *netdev)
/* Need to wait a few seconds after link up to get diagnostic information from
* the phy */
-static void
-e1000_update_phy_info(unsigned long data)
+static void e1000_update_phy_info(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
+ e1000_phy_get_info(hw, &adapter->phy_info);
}
/**
@@ -2564,33 +2568,25 @@ e1000_update_phy_info(unsigned long data)
* @data: pointer to adapter cast into an unsigned long
**/
-static void
-e1000_82547_tx_fifo_stall(unsigned long data)
+static void e1000_82547_tx_fifo_stall(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
u32 tctl;
if (atomic_read(&adapter->tx_fifo_stall)) {
- if ((E1000_READ_REG(&adapter->hw, TDT) ==
- E1000_READ_REG(&adapter->hw, TDH)) &&
- (E1000_READ_REG(&adapter->hw, TDFT) ==
- E1000_READ_REG(&adapter->hw, TDFH)) &&
- (E1000_READ_REG(&adapter->hw, TDFTS) ==
- E1000_READ_REG(&adapter->hw, TDFHS))) {
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
- E1000_WRITE_REG(&adapter->hw, TCTL,
- tctl & ~E1000_TCTL_EN);
- E1000_WRITE_REG(&adapter->hw, TDFT,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFH,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFTS,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TDFHS,
- adapter->tx_head_addr);
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
- E1000_WRITE_FLUSH(&adapter->hw);
+ if ((er32(TDT) == er32(TDH)) &&
+ (er32(TDFT) == er32(TDFH)) &&
+ (er32(TDFTS) == er32(TDFHS))) {
+ tctl = er32(TCTL);
+ ew32(TCTL, tctl & ~E1000_TCTL_EN);
+ ew32(TDFT, adapter->tx_head_addr);
+ ew32(TDFH, adapter->tx_head_addr);
+ ew32(TDFTS, adapter->tx_head_addr);
+ ew32(TDFHS, adapter->tx_head_addr);
+ ew32(TCTL, tctl);
+ E1000_WRITE_FLUSH();
adapter->tx_fifo_head = 0;
atomic_set(&adapter->tx_fifo_stall, 0);
@@ -2605,45 +2601,45 @@ e1000_82547_tx_fifo_stall(unsigned long data)
* e1000_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
**/
-static void
-e1000_watchdog(unsigned long data)
+static void e1000_watchdog(unsigned long data)
{
- struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_ring *txdr = adapter->tx_ring;
u32 link, tctl;
s32 ret_val;
- ret_val = e1000_check_for_link(&adapter->hw);
+ ret_val = e1000_check_for_link(hw);
if ((ret_val == E1000_ERR_PHY) &&
- (adapter->hw.phy_type == e1000_phy_igp_3) &&
- (E1000_READ_REG(&adapter->hw, CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
+ (hw->phy_type == e1000_phy_igp_3) &&
+ (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
/* See e1000_kumeran_lock_loss_workaround() */
DPRINTK(LINK, INFO,
"Gigabit has been disabled, downgrading speed\n");
}
- if (adapter->hw.mac_type == e1000_82573) {
- e1000_enable_tx_pkt_filtering(&adapter->hw);
- if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ if (hw->mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(hw);
+ if (adapter->mng_vlan_id != hw->mng_cookie.vlan_id)
e1000_update_mng_vlan(adapter);
}
- if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
- link = !adapter->hw.serdes_link_down;
+ if ((hw->media_type == e1000_media_type_internal_serdes) &&
+ !(er32(TXCW) & E1000_TXCW_ANE))
+ link = !hw->serdes_link_down;
else
- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
+ link = er32(STATUS) & E1000_STATUS_LU;
if (link) {
if (!netif_carrier_ok(netdev)) {
u32 ctrl;
bool txb2b = true;
- e1000_get_speed_and_duplex(&adapter->hw,
+ e1000_get_speed_and_duplex(hw,
&adapter->link_speed,
&adapter->link_duplex);
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, "
"Flow Control: %s\n",
adapter->link_speed,
@@ -2671,19 +2667,19 @@ e1000_watchdog(unsigned long data)
break;
}
- if ((adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572) &&
+ if ((hw->mac_type == e1000_82571 ||
+ hw->mac_type == e1000_82572) &&
!txb2b) {
u32 tarc0;
- tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+ tarc0 = er32(TARC0);
tarc0 &= ~(1 << 21);
- E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+ ew32(TARC0, tarc0);
}
/* disable TSO for pcie and 10/100 speeds, to avoid
* some hardware issues */
if (!adapter->tso_force &&
- adapter->hw.bus_type == e1000_bus_type_pci_express){
+ hw->bus_type == e1000_bus_type_pci_express){
switch (adapter->link_speed) {
case SPEED_10:
case SPEED_100:
@@ -2704,9 +2700,9 @@ e1000_watchdog(unsigned long data)
/* enable transmits in the hardware, need to do this
* after setting TARC0 */
- tctl = E1000_READ_REG(&adapter->hw, TCTL);
+ tctl = er32(TCTL);
tctl |= E1000_TCTL_EN;
- E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+ ew32(TCTL, tctl);
netif_carrier_on(netdev);
netif_wake_queue(netdev);
@@ -2714,10 +2710,9 @@ e1000_watchdog(unsigned long data)
adapter->smartspeed = 0;
} else {
/* make sure the receive unit is started */
- if (adapter->hw.rx_needs_kicking) {
- struct e1000_hw *hw = &adapter->hw;
- u32 rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+ if (hw->rx_needs_kicking) {
+ u32 rctl = er32(RCTL);
+ ew32(RCTL, rctl | E1000_RCTL_EN);
}
}
} else {
@@ -2734,7 +2729,7 @@ e1000_watchdog(unsigned long data)
* disable receives in the ISR and
* reset device here in the watchdog
*/
- if (adapter->hw.mac_type == e1000_80003es2lan)
+ if (hw->mac_type == e1000_80003es2lan)
/* reset device */
schedule_work(&adapter->reset_task);
}
@@ -2744,9 +2739,9 @@ e1000_watchdog(unsigned long data)
e1000_update_stats(adapter);
- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
+ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
adapter->tpt_old = adapter->stats.tpt;
- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
+ hw->collision_delta = adapter->stats.colc - adapter->colc_old;
adapter->colc_old = adapter->stats.colc;
adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
@@ -2754,7 +2749,7 @@ e1000_watchdog(unsigned long data)
adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
adapter->gotcl_old = adapter->stats.gotcl;
- e1000_update_adaptive(&adapter->hw);
+ e1000_update_adaptive(hw);
if (!netif_carrier_ok(netdev)) {
if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
@@ -2768,15 +2763,15 @@ e1000_watchdog(unsigned long data)
}
/* Cause software interrupt to ensure rx ring is cleaned */
- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+ ew32(ICS, E1000_ICS_RXDMT0);
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = true;
/* With 82571 controllers, LAA may be overwritten due to controller
* reset from the other port. Set the appropriate LAA in RAR[0] */
- if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+ if (hw->mac_type == e1000_82571 && hw->laa_is_present)
+ e1000_rar_set(hw, hw->mac_addr, 0);
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
@@ -2806,9 +2801,7 @@ enum latency_range {
* @bytes: the number of bytes during this measurement interval
**/
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
- u16 itr_setting,
- int packets,
- int bytes)
+ u16 itr_setting, int packets, int bytes)
{
unsigned int retval = itr_setting;
struct e1000_hw *hw = &adapter->hw;
@@ -2913,7 +2906,7 @@ set_itr_now:
min(adapter->itr + (new_itr >> 2), new_itr) :
new_itr;
adapter->itr = new_itr;
- E1000_WRITE_REG(hw, ITR, 1000000000 / (new_itr * 256));
+ ew32(ITR, 1000000000 / (new_itr * 256));
}
return;
@@ -2926,9 +2919,8 @@ set_itr_now:
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
-static int
-e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+static int e1000_tso(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
@@ -2999,9 +2991,8 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
return false;
}
-static bool
-e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
@@ -3038,11 +3029,13 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
#define E1000_MAX_TXD_PWR 12
#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
-static int
-e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
- unsigned int nr_frags, unsigned int mss)
+static int e1000_tx_map(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring,
+ struct sk_buff *skb, unsigned int first,
+ unsigned int max_per_txd, unsigned int nr_frags,
+ unsigned int mss)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_buffer *buffer_info;
unsigned int len = skb->len;
unsigned int offset = 0, size, count = 0, i;
@@ -3073,7 +3066,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* The fix is to make sure that the first descriptor of a
* packet is smaller than 2048 - 16 - 16 (or 2016) bytes
*/
- if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
(size > 2015) && count == 0))
size = 2015;
@@ -3145,10 +3138,11 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
return count;
}
-static void
-e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
- int tx_flags, int count)
+static void e1000_tx_queue(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring, int tx_flags,
+ int count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_desc *tx_desc = NULL;
struct e1000_buffer *buffer_info;
u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -3194,7 +3188,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
wmb();
tx_ring->next_to_use = i;
- writel(i, adapter->hw.hw_addr + tx_ring->tdt);
+ writel(i, hw->hw_addr + tx_ring->tdt);
/* we need this if more than one processor can write to our tail
* at a time, it syncronizes IO on IA64/Altix systems */
mmiowb();
@@ -3212,8 +3206,8 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
#define E1000_FIFO_HDR 0x10
#define E1000_82547_PAD_LEN 0x3E0
-static int
-e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+ struct sk_buff *skb)
{
u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
@@ -3239,19 +3233,19 @@ no_fifo_stall_required:
}
#define MINIMUM_DHCP_PACKET_SIZE 282
-static int
-e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
+ struct sk_buff *skb)
{
struct e1000_hw *hw = &adapter->hw;
u16 length, offset;
if (vlan_tx_tag_present(skb)) {
- if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
- ( adapter->hw.mng_cookie.status &
+ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) &&
+ ( hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
- struct ethhdr *eth = (struct ethhdr *) skb->data;
+ struct ethhdr *eth = (struct ethhdr *)skb->data;
if ((htons(ETH_P_IP) == eth->h_proto)) {
const struct iphdr *ip =
(struct iphdr *)((u8 *)skb->data+14);
@@ -3304,10 +3298,10 @@ static int e1000_maybe_stop_tx(struct net_device *netdev,
}
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
-static int
-e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct e1000_tx_ring *tx_ring;
unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
@@ -3333,7 +3327,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* 82571 and newer doesn't need the workaround that limited descriptor
* length to 4kB */
- if (adapter->hw.mac_type >= e1000_82571)
+ if (hw->mac_type >= e1000_82571)
max_per_txd = 8192;
mss = skb_shinfo(skb)->gso_size;
@@ -3353,7 +3347,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* frags into skb->data */
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
if (skb->data_len && hdr_len == len) {
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
unsigned int pull_size;
case e1000_82544:
/* Make sure we have room to chop off 4 bytes,
@@ -3402,7 +3396,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* work-around for errata 10 and it applies to all controllers
* in PCI-X mode, so add one more descriptor to the count
*/
- if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
(len > 2015)))
count++;
@@ -3414,8 +3408,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
count += nr_frags;
- if (adapter->hw.tx_pkt_filtering &&
- (adapter->hw.mac_type == e1000_82573))
+ if (hw->tx_pkt_filtering &&
+ (hw->mac_type == e1000_82573))
e1000_transfer_dhcp_info(adapter, skb);
if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags))
@@ -3429,7 +3423,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+ if (unlikely(hw->mac_type == e1000_82547)) {
if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
@@ -3482,8 +3476,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* @netdev: network interface device structure
**/
-static void
-e1000_tx_timeout(struct net_device *netdev)
+static void e1000_tx_timeout(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3492,8 +3485,7 @@ e1000_tx_timeout(struct net_device *netdev)
schedule_work(&adapter->reset_task);
}
-static void
-e1000_reset_task(struct work_struct *work)
+static void e1000_reset_task(struct work_struct *work)
{
struct e1000_adapter *adapter =
container_of(work, struct e1000_adapter, reset_task);
@@ -3509,8 +3501,7 @@ e1000_reset_task(struct work_struct *work)
* The statistics are actually updated from the timer callback.
**/
-static struct net_device_stats *
-e1000_get_stats(struct net_device *netdev)
+static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -3526,10 +3517,10 @@ e1000_get_stats(struct net_device *netdev)
* Returns 0 on success, negative on failure
**/
-static int
-e1000_change_mtu(struct net_device *netdev, int new_mtu)
+static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
u16 eeprom_data = 0;
@@ -3540,7 +3531,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
}
/* Adapter-specific max frame size limits. */
- switch (adapter->hw.mac_type) {
+ switch (hw->mac_type) {
case e1000_undefined ... e1000_82542_rev2_1:
case e1000_ich8lan:
if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
@@ -3552,9 +3543,9 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
/* Jumbo Frames not supported if:
* - this is not an 82573L device
* - ASPM is enabled in any way (0x1A bits 3:2) */
- e1000_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
+ e1000_read_eeprom(hw, EEPROM_INIT_3GIO_3, 1,
&eeprom_data);
- if ((adapter->hw.device_id != E1000_DEV_ID_82573L) ||
+ if ((hw->device_id != E1000_DEV_ID_82573L) ||
(eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
DPRINTK(PROBE, ERR,
@@ -3601,13 +3592,13 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
adapter->rx_buffer_len = E1000_RXBUFFER_16384;
/* adjust allocation if LPE protects us, and we aren't using SBP */
- if (!adapter->hw.tbi_compatibility_on &&
+ if (!hw->tbi_compatibility_on &&
((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
netdev->mtu = new_mtu;
- adapter->hw.max_frame_size = max_frame;
+ hw->max_frame_size = max_frame;
if (netif_running(netdev))
e1000_reinit_locked(adapter);
@@ -3620,8 +3611,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
* @adapter: board private structure
**/
-void
-e1000_update_stats(struct e1000_adapter *adapter)
+void e1000_update_stats(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
@@ -3646,89 +3636,89 @@ e1000_update_stats(struct e1000_adapter *adapter)
* be written while holding adapter->stats_lock
*/
- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
- adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
- adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
- adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
- adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
- adapter->stats.roc += E1000_READ_REG(hw, ROC);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
- }
-
- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
- adapter->stats.mpc += E1000_READ_REG(hw, MPC);
- adapter->stats.scc += E1000_READ_REG(hw, SCC);
- adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
- adapter->stats.mcc += E1000_READ_REG(hw, MCC);
- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
- adapter->stats.dc += E1000_READ_REG(hw, DC);
- adapter->stats.sec += E1000_READ_REG(hw, SEC);
- adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
- adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
- adapter->stats.ruc += E1000_READ_REG(hw, RUC);
- adapter->stats.rfc += E1000_READ_REG(hw, RFC);
- adapter->stats.rjc += E1000_READ_REG(hw, RJC);
- adapter->stats.torl += E1000_READ_REG(hw, TORL);
- adapter->stats.torh += E1000_READ_REG(hw, TORH);
- adapter->stats.totl += E1000_READ_REG(hw, TOTL);
- adapter->stats.toth += E1000_READ_REG(hw, TOTH);
- adapter->stats.tpr += E1000_READ_REG(hw, TPR);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
- }
-
- adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
- adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
+ adapter->stats.crcerrs += er32(CRCERRS);
+ adapter->stats.gprc += er32(GPRC);
+ adapter->stats.gorcl += er32(GORCL);
+ adapter->stats.gorch += er32(GORCH);
+ adapter->stats.bprc += er32(BPRC);
+ adapter->stats.mprc += er32(MPRC);
+ adapter->stats.roc += er32(ROC);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.prc64 += er32(PRC64);
+ adapter->stats.prc127 += er32(PRC127);
+ adapter->stats.prc255 += er32(PRC255);
+ adapter->stats.prc511 += er32(PRC511);
+ adapter->stats.prc1023 += er32(PRC1023);
+ adapter->stats.prc1522 += er32(PRC1522);
+ }
+
+ adapter->stats.symerrs += er32(SYMERRS);
+ adapter->stats.mpc += er32(MPC);
+ adapter->stats.scc += er32(SCC);
+ adapter->stats.ecol += er32(ECOL);
+ adapter->stats.mcc += er32(MCC);
+ adapter->stats.latecol += er32(LATECOL);
+ adapter->stats.dc += er32(DC);
+ adapter->stats.sec += er32(SEC);
+ adapter->stats.rlec += er32(RLEC);
+ adapter->stats.xonrxc += er32(XONRXC);
+ adapter->stats.xontxc += er32(XONTXC);
+ adapter->stats.xoffrxc += er32(XOFFRXC);
+ adapter->stats.xofftxc += er32(XOFFTXC);
+ adapter->stats.fcruc += er32(FCRUC);
+ adapter->stats.gptc += er32(GPTC);
+ adapter->stats.gotcl += er32(GOTCL);
+ adapter->stats.gotch += er32(GOTCH);
+ adapter->stats.rnbc += er32(RNBC);
+ adapter->stats.ruc += er32(RUC);
+ adapter->stats.rfc += er32(RFC);
+ adapter->stats.rjc += er32(RJC);
+ adapter->stats.torl += er32(TORL);
+ adapter->stats.torh += er32(TORH);
+ adapter->stats.totl += er32(TOTL);
+ adapter->stats.toth += er32(TOTH);
+ adapter->stats.tpr += er32(TPR);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.ptc64 += er32(PTC64);
+ adapter->stats.ptc127 += er32(PTC127);
+ adapter->stats.ptc255 += er32(PTC255);
+ adapter->stats.ptc511 += er32(PTC511);
+ adapter->stats.ptc1023 += er32(PTC1023);
+ adapter->stats.ptc1522 += er32(PTC1522);
+ }
+
+ adapter->stats.mptc += er32(MPTC);
+ adapter->stats.bptc += er32(BPTC);
/* used for adaptive IFS */
- hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
+ hw->tx_packet_delta = er32(TPT);
adapter->stats.tpt += hw->tx_packet_delta;
- hw->collision_delta = E1000_READ_REG(hw, COLC);
+ hw->collision_delta = er32(COLC);
adapter->stats.colc += hw->collision_delta;
if (hw->mac_type >= e1000_82543) {
- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
+ adapter->stats.algnerrc += er32(ALGNERRC);
+ adapter->stats.rxerrc += er32(RXERRC);
+ adapter->stats.tncrs += er32(TNCRS);
+ adapter->stats.cexterr += er32(CEXTERR);
+ adapter->stats.tsctc += er32(TSCTC);
+ adapter->stats.tsctfc += er32(TSCTFC);
}
if (hw->mac_type > e1000_82547_rev_2) {
- adapter->stats.iac += E1000_READ_REG(hw, IAC);
- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
-
- if (adapter->hw.mac_type != e1000_ich8lan) {
- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ adapter->stats.iac += er32(IAC);
+ adapter->stats.icrxoc += er32(ICRXOC);
+
+ if (hw->mac_type != e1000_ich8lan) {
+ adapter->stats.icrxptc += er32(ICRXPTC);
+ adapter->stats.icrxatc += er32(ICRXATC);
+ adapter->stats.ictxptc += er32(ICTXPTC);
+ adapter->stats.ictxatc += er32(ICTXATC);
+ adapter->stats.ictxqec += er32(ICTXQEC);
+ adapter->stats.ictxqmtc += er32(ICTXQMTC);
+ adapter->stats.icrxdmtc += er32(ICRXDMTC);
}
}
@@ -3756,7 +3746,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
adapter->net_stats.tx_window_errors = adapter->stats.latecol;
adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
- if (adapter->hw.bad_tx_carr_stats_fd &&
+ if (hw->bad_tx_carr_stats_fd &&
adapter->link_duplex == FULL_DUPLEX) {
adapter->net_stats.tx_carrier_errors = 0;
adapter->stats.tncrs = 0;
@@ -3779,10 +3769,10 @@ e1000_update_stats(struct e1000_adapter *adapter)
}
/* Management Stats */
- if (adapter->hw.has_smbus) {
- adapter->stats.mgptc += E1000_READ_REG(hw, MGTPTC);
- adapter->stats.mgprc += E1000_READ_REG(hw, MGTPRC);
- adapter->stats.mgpdc += E1000_READ_REG(hw, MGTPDC);
+ if (hw->has_smbus) {
+ adapter->stats.mgptc += er32(MGTPTC);
+ adapter->stats.mgprc += er32(MGTPRC);
+ adapter->stats.mgpdc += er32(MGTPDC);
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
@@ -3794,16 +3784,12 @@ e1000_update_stats(struct e1000_adapter *adapter)
* @data: pointer to a network interface device structure
**/
-static irqreturn_t
-e1000_intr_msi(int irq, void *data)
+static irqreturn_t e1000_intr_msi(int irq, void *data)
{
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-#ifndef CONFIG_E1000_NAPI
- int i;
-#endif
- u32 icr = E1000_READ_REG(hw, ICR);
+ u32 icr = er32(ICR);
/* in NAPI mode read ICR disables interrupts using IAM */
@@ -3813,17 +3799,16 @@ e1000_intr_msi(int irq, void *data)
* link down event; disable receives here in the ISR and reset
* adapter in watchdog */
if (netif_carrier_ok(netdev) &&
- (adapter->hw.mac_type == e1000_80003es2lan)) {
+ (hw->mac_type == e1000_80003es2lan)) {
/* disable receives */
- u32 rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ u32 rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_E1000_NAPI
if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
@@ -3832,20 +3817,6 @@ e1000_intr_msi(int irq, void *data)
__netif_rx_schedule(netdev, &adapter->napi);
} else
e1000_irq_enable(adapter);
-#else
- adapter->total_tx_bytes = 0;
- adapter->total_rx_bytes = 0;
- adapter->total_tx_packets = 0;
- adapter->total_rx_packets = 0;
-
- for (i = 0; i < E1000_MAX_INTR; i++)
- if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
- !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
- break;
-
- if (likely(adapter->itr_setting & 3))
- e1000_set_itr(adapter);
-#endif
return IRQ_HANDLED;
}
@@ -3856,20 +3827,16 @@ e1000_intr_msi(int irq, void *data)
* @data: pointer to a network interface device structure
**/
-static irqreturn_t
-e1000_intr(int irq, void *data)
+static irqreturn_t e1000_intr(int irq, void *data)
{
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 rctl, icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
- int i;
-#endif
+ u32 rctl, icr = er32(ICR);
+
if (unlikely(!icr))
return IRQ_NONE; /* Not our interrupt */
-#ifdef CONFIG_E1000_NAPI
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
* not set, then the adapter didn't send an interrupt */
if (unlikely(hw->mac_type >= e1000_82571 &&
@@ -3878,7 +3845,6 @@ e1000_intr(int irq, void *data)
/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
* need for the IMC write */
-#endif
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
@@ -3888,21 +3854,20 @@ e1000_intr(int irq, void *data)
* reset adapter in watchdog
*/
if (netif_carrier_ok(netdev) &&
- (adapter->hw.mac_type == e1000_80003es2lan)) {
+ (hw->mac_type == e1000_80003es2lan)) {
/* disable receives */
- rctl = E1000_READ_REG(hw, RCTL);
- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+ rctl = er32(RCTL);
+ ew32(RCTL, rctl & ~E1000_RCTL_EN);
}
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
-#ifdef CONFIG_E1000_NAPI
if (unlikely(hw->mac_type < e1000_82571)) {
/* disable interrupts, without the synchronize_irq bit */
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
+ ew32(IMC, ~0);
+ E1000_WRITE_FLUSH();
}
if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
adapter->total_tx_bytes = 0;
@@ -3914,48 +3879,15 @@ e1000_intr(int irq, void *data)
/* this really should not happen! if it does it is basically a
* bug, but not a hard error, so enable ints and continue */
e1000_irq_enable(adapter);
-#else
- /* Writing IMC and IMS is needed for 82547.
- * Due to Hub Link bus being occupied, an interrupt
- * de-assertion message is not able to be sent.
- * When an interrupt assertion message is generated later,
- * two messages are re-ordered and sent out.
- * That causes APIC to think 82547 is in de-assertion
- * state, while 82547 is in assertion state, resulting
- * in dead lock. Writing IMC forces 82547 into
- * de-assertion state.
- */
- if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
- E1000_WRITE_REG(hw, IMC, ~0);
-
- adapter->total_tx_bytes = 0;
- adapter->total_rx_bytes = 0;
- adapter->total_tx_packets = 0;
- adapter->total_rx_packets = 0;
- for (i = 0; i < E1000_MAX_INTR; i++)
- if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
- !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
- break;
-
- if (likely(adapter->itr_setting & 3))
- e1000_set_itr(adapter);
-
- if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
- e1000_irq_enable(adapter);
-
-#endif
return IRQ_HANDLED;
}
-#ifdef CONFIG_E1000_NAPI
/**
* e1000_clean - NAPI Rx polling callback
* @adapter: board private structure
**/
-
-static int
-e1000_clean(struct napi_struct *napi, int budget)
+static int e1000_clean(struct napi_struct *napi, int budget)
{
struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
struct net_device *poll_dev = adapter->netdev;
@@ -3991,23 +3923,19 @@ e1000_clean(struct napi_struct *napi, int budget)
return work_done;
}
-#endif
/**
* e1000_clean_tx_irq - Reclaim resources after transmit completes
* @adapter: board private structure
**/
-
-static bool
-e1000_clean_tx_irq(struct e1000_adapter *adapter,
- struct e1000_tx_ring *tx_ring)
+static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
+ struct e1000_tx_ring *tx_ring)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct e1000_buffer *buffer_info;
unsigned int i, eop;
-#ifdef CONFIG_E1000_NAPI
unsigned int count = 0;
-#endif
bool cleaned = false;
unsigned int total_tx_bytes=0, total_tx_packets=0;
@@ -4039,11 +3967,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
-#ifdef CONFIG_E1000_NAPI
#define E1000_TX_WEIGHT 64
/* weight of a sort for tx, to avoid endless transmit cleanup */
- if (count++ == E1000_TX_WEIGHT) break;
-#endif
+ if (count++ == E1000_TX_WEIGHT)
+ break;
}
tx_ring->next_to_clean = i;
@@ -4068,8 +3995,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
if (tx_ring->buffer_info[eop].dma &&
time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
(adapter->tx_timeout_factor * HZ))
- && !(E1000_READ_REG(&adapter->hw, STATUS) &
- E1000_STATUS_TXOFF)) {
+ && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
@@ -4085,8 +4011,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
" next_to_watch.status <%x>\n",
(unsigned long)((tx_ring - adapter->tx_ring) /
sizeof(struct e1000_tx_ring)),
- readl(adapter->hw.hw_addr + tx_ring->tdh),
- readl(adapter->hw.hw_addr + tx_ring->tdt),
+ readl(hw->hw_addr + tx_ring->tdh),
+ readl(hw->hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
tx_ring->next_to_clean,
tx_ring->buffer_info[eop].time_stamp,
@@ -4111,17 +4037,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
* @sk_buff: socket buffer with received data
**/
-static void
-e1000_rx_checksum(struct e1000_adapter *adapter,
- u32 status_err, u32 csum,
- struct sk_buff *skb)
+static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
+ u32 csum, struct sk_buff *skb)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 status = (u16)status_err;
u8 errors = (u8)(status_err >> 24);
skb->ip_summed = CHECKSUM_NONE;
/* 82543 or newer only */
- if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
+ if (unlikely(hw->mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
/* TCP/UDP checksum error bit is set */
@@ -4131,7 +4056,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
return;
}
/* TCP/UDP Checksum has not been calculated */
- if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if (hw->mac_type <= e1000_82547_rev_2) {
if (!(status & E1000_RXD_STAT_TCPCS))
return;
} else {
@@ -4142,7 +4067,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
if (likely(status & E1000_RXD_STAT_TCPCS)) {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ } else if (hw->mac_type > e1000_82547_rev_2) {
/* IP fragment with UDP payload */
/* Hardware complements the payload checksum, so we undo it
* and then put the value in host order for further stack use.
@@ -4158,17 +4083,11 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
* e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
**/
-
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc, *next_rxd;
@@ -4189,11 +4108,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
struct sk_buff *skb;
u8 status;
-#ifdef CONFIG_E1000_NAPI
if (*work_done >= work_to_do)
break;
(*work_done)++;
-#endif
+
status = rx_desc->status;
skb = buffer_info->skb;
buffer_info->skb = NULL;
@@ -4226,11 +4144,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
- if (TBI_ACCEPT(&adapter->hw, status,
- rx_desc->errors, length, last_byte)) {
+ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
+ last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
- e1000_tbi_adjust_stats(&adapter->hw,
- &adapter->stats,
+ e1000_tbi_adjust_stats(hw, &adapter->stats,
length, skb->data);
spin_unlock_irqrestore(&adapter->stats_lock,
flags);
@@ -4280,7 +4197,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
le16_to_cpu(rx_desc->csum), skb);
skb->protocol = eth_type_trans(skb, netdev);
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(adapter->vlgrp &&
(status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -4288,15 +4205,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_E1000_NAPI */
- if (unlikely(adapter->vlgrp &&
- (status & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->special));
- } else {
- netif_rx(skb);
- }
-#endif /* CONFIG_E1000_NAPI */
+
netdev->last_rx = jiffies;
next_desc:
@@ -4330,15 +4239,9 @@ next_desc:
* @adapter: board private structure
**/
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do)
{
union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
@@ -4361,11 +4264,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
while (staterr & E1000_RXD_STAT_DD) {
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(*work_done >= work_to_do))
break;
(*work_done)++;
-#endif
+
skb = buffer_info->skb;
/* in the packet split case this is header only */
@@ -4438,7 +4341,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
for (j = 0; j < adapter->rx_ps_pages; j++) {
- if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j])))
+ length = le16_to_cpu(rx_desc->wb.upper.length[j]);
+ if (!length)
break;
pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
PAGE_SIZE, PCI_DMA_FROMDEVICE);
@@ -4466,21 +4370,14 @@ copydone:
if (likely(rx_desc->wb.upper.header_status &
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
adapter->rx_hdr_split++;
-#ifdef CONFIG_E1000_NAPI
+
if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan));
} else {
netif_receive_skb(skb);
}
-#else /* CONFIG_E1000_NAPI */
- if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
- vlan_hwaccel_rx(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->wb.middle.vlan));
- } else {
- netif_rx(skb);
- }
-#endif /* CONFIG_E1000_NAPI */
+
netdev->last_rx = jiffies;
next_desc:
@@ -4517,11 +4414,11 @@ next_desc:
* @adapter: address of board private structure
**/
-static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count)
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
@@ -4619,7 +4516,7 @@ map_skb:
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(i, hw->hw_addr + rx_ring->rdt);
}
}
@@ -4628,11 +4525,11 @@ map_skb:
* @adapter: address of board private structure
**/
-static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int cleaned_count)
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
+ struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
union e1000_rx_desc_packet_split *rx_desc;
@@ -4717,7 +4614,7 @@ no_buffers:
* descriptors are 32 bytes...so we increment tail
* twice as much.
*/
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ writel(i<<1, hw->hw_addr + rx_ring->rdt);
}
}
@@ -4726,49 +4623,49 @@ no_buffers:
* @adapter:
**/
-static void
-e1000_smartspeed(struct e1000_adapter *adapter)
+static void e1000_smartspeed(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
u16 phy_status;
u16 phy_ctrl;
- if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
- !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
+ if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
+ !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
return;
if (adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
if (phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
- e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
+ e1000_write_phy_reg(hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
- if (!e1000_phy_setup_autoneg(&adapter->hw) &&
- !e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
+ if (!e1000_phy_setup_autoneg(hw) &&
+ !e1000_read_phy_reg(hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL,
+ e1000_write_phy_reg(hw, PHY_CTRL,
phy_ctrl);
}
}
return;
} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
- e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
- e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
- if (!e1000_phy_setup_autoneg(&adapter->hw) &&
- !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
+ e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
+ if (!e1000_phy_setup_autoneg(hw) &&
+ !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
@@ -4783,8 +4680,7 @@ e1000_smartspeed(struct e1000_adapter *adapter)
* @cmd:
**/
-static int
-e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
switch (cmd) {
case SIOCGMIIPHY:
@@ -4803,28 +4699,29 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* @cmd:
**/
-static int
-e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ int cmd)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct mii_ioctl_data *data = if_mii(ifr);
int retval;
u16 mii_reg;
u16 spddplx;
unsigned long flags;
- if (adapter->hw.media_type != e1000_media_type_copper)
+ if (hw->media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
switch (cmd) {
case SIOCGMIIPHY:
- data->phy_id = adapter->hw.phy_addr;
+ data->phy_id = hw->phy_addr;
break;
case SIOCGMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
&data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
@@ -4838,20 +4735,20 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return -EFAULT;
mii_reg = data->val_in;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ if (e1000_write_phy_reg(hw, data->reg_num,
mii_reg)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
- if (adapter->hw.media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
switch (data->reg_num) {
case PHY_CTRL:
if (mii_reg & MII_CR_POWER_DOWN)
break;
if (mii_reg & MII_CR_AUTO_NEG_EN) {
- adapter->hw.autoneg = 1;
- adapter->hw.autoneg_advertised = 0x2F;
+ hw->autoneg = 1;
+ hw->autoneg_advertised = 0x2F;
} else {
if (mii_reg & 0x40)
spddplx = SPEED_1000;
@@ -4874,7 +4771,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw))
+ if (e1000_phy_reset(hw))
return -EIO;
break;
}
@@ -4897,8 +4794,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
return E1000_SUCCESS;
}
-void
-e1000_pci_set_mwi(struct e1000_hw *hw)
+void e1000_pci_set_mwi(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
int ret_val = pci_set_mwi(adapter->pdev);
@@ -4907,30 +4803,26 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
-void
-e1000_pci_clear_mwi(struct e1000_hw *hw)
+void e1000_pci_clear_mwi(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
pci_clear_mwi(adapter->pdev);
}
-int
-e1000_pcix_get_mmrbc(struct e1000_hw *hw)
+int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
return pcix_get_mmrbc(adapter->pdev);
}
-void
-e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
{
struct e1000_adapter *adapter = hw->back;
pcix_set_mmrbc(adapter->pdev, mmrbc);
}
-s32
-e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct e1000_adapter *adapter = hw->back;
u16 cap_offset;
@@ -4944,16 +4836,16 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
return E1000_SUCCESS;
}
-void
-e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
+void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
{
outl(value, port);
}
-static void
-e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void e1000_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl, rctl;
if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -4962,22 +4854,22 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
if (grp) {
/* enable VLAN tag insert/strip */
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
/* enable VLAN receive filtering */
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl &= ~E1000_RCTL_CFIEN;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
e1000_update_mng_vlan(adapter);
}
} else {
/* disable VLAN tag insert/strip */
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ ctrl = er32(CTRL);
ctrl &= ~E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
if (adapter->hw.mac_type != e1000_ich8lan) {
if (adapter->mng_vlan_id !=
@@ -4993,27 +4885,27 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_irq_enable(adapter);
}
-static void
-e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 vfta, index;
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
(vid == adapter->mng_vlan_id))
return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta |= (1 << (vid & 0x1F));
- e1000_write_vfta(&adapter->hw, index, vfta);
+ e1000_write_vfta(hw, index, vfta);
}
-static void
-e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 vfta, index;
if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -5022,7 +4914,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
- if ((adapter->hw.mng_cookie.status &
+ if ((hw->mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
(vid == adapter->mng_vlan_id)) {
/* release control to f/w */
@@ -5032,13 +4924,12 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
vfta &= ~(1 << (vid & 0x1F));
- e1000_write_vfta(&adapter->hw, index, vfta);
+ e1000_write_vfta(hw, index, vfta);
}
-static void
-e1000_restore_vlan(struct e1000_adapter *adapter)
+static void e1000_restore_vlan(struct e1000_adapter *adapter)
{
e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
@@ -5052,13 +4943,14 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
}
}
-int
-e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
{
- adapter->hw.autoneg = 0;
+ struct e1000_hw *hw = &adapter->hw;
+
+ hw->autoneg = 0;
/* Fiber NICs only allow 1000 gbps Full duplex */
- if ((adapter->hw.media_type == e1000_media_type_fiber) &&
+ if ((hw->media_type == e1000_media_type_fiber) &&
spddplx != (SPEED_1000 + DUPLEX_FULL)) {
DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
@@ -5066,20 +4958,20 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
- adapter->hw.forced_speed_duplex = e1000_10_half;
+ hw->forced_speed_duplex = e1000_10_half;
break;
case SPEED_10 + DUPLEX_FULL:
- adapter->hw.forced_speed_duplex = e1000_10_full;
+ hw->forced_speed_duplex = e1000_10_full;
break;
case SPEED_100 + DUPLEX_HALF:
- adapter->hw.forced_speed_duplex = e1000_100_half;
+ hw->forced_speed_duplex = e1000_100_half;
break;
case SPEED_100 + DUPLEX_FULL:
- adapter->hw.forced_speed_duplex = e1000_100_full;
+ hw->forced_speed_duplex = e1000_100_full;
break;
case SPEED_1000 + DUPLEX_FULL:
- adapter->hw.autoneg = 1;
- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
+ hw->autoneg = 1;
+ hw->autoneg_advertised = ADVERTISE_1000_FULL;
break;
case SPEED_1000 + DUPLEX_HALF: /* not supported */
default:
@@ -5089,11 +4981,11 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
return 0;
}
-static int
-e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 ctrl, ctrl_ext, rctl, status;
u32 wufc = adapter->wol;
#ifdef CONFIG_PM
@@ -5113,7 +5005,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
return retval;
#endif
- status = E1000_READ_REG(&adapter->hw, STATUS);
+ status = er32(STATUS);
if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
@@ -5123,40 +5015,40 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
/* turn on all-multi mode if wake on multicast is enabled */
if (wufc & E1000_WUFC_MC) {
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = er32(RCTL);
rctl |= E1000_RCTL_MPE;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ ew32(RCTL, rctl);
}
- if (adapter->hw.mac_type >= e1000_82540) {
- ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+ if (hw->mac_type >= e1000_82540) {
+ ctrl = er32(CTRL);
/* advertise wake from D3Cold */
#define E1000_CTRL_ADVD3WUC 0x00100000
/* phy power management enable */
#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
ctrl |= E1000_CTRL_ADVD3WUC |
E1000_CTRL_EN_PHY_PWR_MGMT;
- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+ ew32(CTRL, ctrl);
}
- if (adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) {
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
+ ew32(CTRL_EXT, ctrl_ext);
}
/* Allow time for pending master requests to run */
- e1000_disable_pciex_master(&adapter->hw);
+ e1000_disable_pciex_master(hw);
- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
- E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
+ ew32(WUC, E1000_WUC_PME_EN);
+ ew32(WUFC, wufc);
pci_enable_wake(pdev, PCI_D3hot, 1);
pci_enable_wake(pdev, PCI_D3cold, 1);
} else {
- E1000_WRITE_REG(&adapter->hw, WUC, 0);
- E1000_WRITE_REG(&adapter->hw, WUFC, 0);
+ ew32(WUC, 0);
+ ew32(WUFC, 0);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
}
@@ -5169,8 +5061,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
pci_enable_wake(pdev, PCI_D3cold, 1);
}
- if (adapter->hw.phy_type == e1000_phy_igp_3)
- e1000_phy_powerdown_workaround(&adapter->hw);
+ if (hw->phy_type == e1000_phy_igp_3)
+ e1000_phy_powerdown_workaround(hw);
if (netif_running(netdev))
e1000_free_irq(adapter);
@@ -5187,16 +5079,21 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
#ifdef CONFIG_PM
-static int
-e1000_resume(struct pci_dev *pdev)
+static int e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
u32 err;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- if ((err = pci_enable_device(pdev))) {
+
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
+ if (err) {
printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
return err;
}
@@ -5205,12 +5102,15 @@ e1000_resume(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
- if (netif_running(netdev) && (err = e1000_request_irq(adapter)))
- return err;
+ if (netif_running(netdev)) {
+ err = e1000_request_irq(adapter);
+ if (err)
+ return err;
+ }
e1000_power_up_phy(adapter);
e1000_reset(adapter);
- E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ ew32(WUS, ~0);
e1000_init_manageability(adapter);
@@ -5223,8 +5123,8 @@ e1000_resume(struct pci_dev *pdev)
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
return 0;
@@ -5242,16 +5142,12 @@ static void e1000_shutdown(struct pci_dev *pdev)
* without having to re-enable interrupts. It's not called while
* the interrupt routine is executing.
*/
-static void
-e1000_netpoll(struct net_device *netdev)
+static void e1000_netpoll(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev);
-#ifndef CONFIG_E1000_NAPI
- adapter->clean_rx(adapter, adapter->rx_ring);
-#endif
enable_irq(adapter->pdev->irq);
}
#endif
@@ -5264,7 +5160,8 @@ e1000_netpoll(struct net_device *netdev)
* This function is called after a PCI bus error affecting
* this device has been detected.
*/
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
@@ -5290,8 +5187,14 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_hw *hw = &adapter->hw;
+ int err;
- if (pci_enable_device(pdev)) {
+ if (adapter->need_ioport)
+ err = pci_enable_device(pdev);
+ else
+ err = pci_enable_device_mem(pdev);
+ if (err) {
printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
@@ -5301,7 +5204,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
pci_enable_wake(pdev, PCI_D3cold, 0);
e1000_reset(adapter);
- E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+ ew32(WUS, ~0);
return PCI_ERS_RESULT_RECOVERED;
}
@@ -5318,6 +5221,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_hw *hw = &adapter->hw;
e1000_init_manageability(adapter);
@@ -5334,8 +5238,8 @@ static void e1000_io_resume(struct pci_dev *pdev)
* DRV_LOAD until the interface is up. For all other cases,
* let the f/w know that the h/w is now under the control
* of the driver. */
- if (adapter->hw.mac_type != e1000_82573 ||
- !e1000_check_mng_mode(&adapter->hw))
+ if (hw->mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(hw))
e1000_get_hw_control(adapter);
}
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 365626d3177..d9298522f5a 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -55,13 +55,13 @@
#define DEBUGOUT7 DEBUGOUT3
-#define E1000_WRITE_REG(a, reg, value) ( \
- writel((value), ((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
+#define er32(reg) \
+ (readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg)))
-#define E1000_READ_REG(a, reg) ( \
- readl((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
+#define ew32(reg, value) \
+ (writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg))))
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
writel((value), ((a)->hw_addr + \
@@ -96,7 +96,7 @@
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
(offset)))
-#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
+#define E1000_WRITE_FLUSH() er32(STATUS)
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
writel((value), ((a)->flash_address + reg)))
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e6565ce686b..b9f90a5d3d4 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -213,10 +213,9 @@ struct e1000_option {
} arg;
};
-static int __devinit
-e1000_validate_option(unsigned int *value,
- const struct e1000_option *opt,
- struct e1000_adapter *adapter)
+static int __devinit e1000_validate_option(unsigned int *value,
+ const struct e1000_option *opt,
+ struct e1000_adapter *adapter)
{
if (*value == OPTION_UNSET) {
*value = opt->def;
@@ -278,8 +277,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter);
* in a variable in the adapter structure.
**/
-void __devinit
-e1000_check_options(struct e1000_adapter *adapter)
+void __devinit e1000_check_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
if (bd >= E1000_MAX_NIC) {
@@ -551,8 +549,7 @@ e1000_check_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on fiber adapters
**/
-static void __devinit
-e1000_check_fiber_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
if (num_Speed > bd) {
@@ -579,8 +576,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
* Handles speed and duplex options on copper adapters
**/
-static void __devinit
-e1000_check_copper_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
{
unsigned int speed, dplx, an;
int bd = adapter->bd_number;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 869544b8c05..9c0f56b3c51 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4067,8 +4067,6 @@ static void e1000_netpoll(struct net_device *netdev)
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev);
- e1000_clean_tx_irq(adapter);
-
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 32a4f17d35f..ecd5c71a7a8 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -2,12 +2,6 @@
* Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
- * This version of the driver is specific to the FADS implementation,
- * since the board contains control registers external to the processor
- * for the control of the LevelOne LXT970 transceiver. The MPC860T manual
- * describes connections using the internal parallel port I/O, which
- * is basically all of Port D.
- *
* Right now, I am very wasteful with the buffers. I allocate memory
* pages and then divide them into 2K frame buffers. This way I know I
* have buffers large enough to hold one frame within one buffer descriptor.
@@ -49,17 +43,9 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
- defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
- defined(CONFIG_M520x) || defined(CONFIG_M532x)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include "fec.h"
-#else
-#include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
-#include "commproc.h"
-#endif
#if defined(CONFIG_FEC2)
#define FEC_MAX_PORTS 2
@@ -67,7 +53,7 @@
#define FEC_MAX_PORTS 1
#endif
-#if defined(CONFIG_FADS) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_M5272)
+#if defined(CONFIG_M5272)
#define HAVE_mii_link_interrupt
#endif
@@ -1235,14 +1221,9 @@ static phy_info_t const * const phy_info[] = {
/* ------------------------------------------------------------------------- */
#ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id);
-#else
static irqreturn_t
mii_link_interrupt(int irq, void * dev_id);
#endif
-#endif
#if defined(CONFIG_M5272)
/*
@@ -1795,24 +1776,6 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
panic("Could not allocate FEC IRQ!");
-
-#ifdef CONFIG_RPXCLASSIC
- /* Make Port C, bit 15 an input that causes interrupts.
- */
- immap->im_ioport.iop_pcpar &= ~0x0001;
- immap->im_ioport.iop_pcdir &= ~0x0001;
- immap->im_ioport.iop_pcso &= ~0x0001;
- immap->im_ioport.iop_pcint |= 0x0001;
- cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev);
-
- /* Make LEDS reflect Link status.
- */
- *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE;
-#endif
-#ifdef CONFIG_FADS
- if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)
- panic("Could not allocate MII IRQ!");
-#endif
}
static void __inline__ fec_get_mac(struct net_device *dev)
@@ -1821,16 +1784,6 @@ static void __inline__ fec_get_mac(struct net_device *dev)
bd = (bd_t *)__res;
memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
-
-#ifdef CONFIG_RPXCLASSIC
- /* The Embedded Planet boards have only one MAC address in
- * the EEPROM, but can have two Ethernet ports. For the
- * FEC port, we create another address by setting one of
- * the address bits above something that would have (up to
- * now) been allocated.
- */
- dev->dev_adrd[3] |= 0x80;
-#endif
}
static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -2109,13 +2062,8 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
/* This interrupt occurs when the PHY detects a link change.
*/
#ifdef HAVE_mii_link_interrupt
-#ifdef CONFIG_RPXCLASSIC
-static void
-mii_link_interrupt(void *dev_id)
-#else
static irqreturn_t
mii_link_interrupt(int irq, void * dev_id)
-#endif
{
struct net_device *dev = dev_id;
struct fec_enet_private *fep = netdev_priv(dev);
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index ae9ecb7df22..4e4f68304e8 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -197,9 +197,6 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev)
if (priv->link == PHY_DOWN) {
new_state = 1;
priv->link = phydev->link;
- netif_tx_schedule_all(dev);
- netif_carrier_on(dev);
- netif_start_queue(dev);
}
} else if (priv->link) {
@@ -207,8 +204,6 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev)
priv->link = PHY_DOWN;
priv->speed = 0;
priv->duplex = -1;
- netif_stop_queue(dev);
- netif_carrier_off(dev);
}
if (new_state && netif_msg_link(priv))
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 1ffbe0756a0..d4a305ee345 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -8,12 +8,7 @@ fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o
fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
-ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-else
-fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
-fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-endif
fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 445763e5648..9a51ec8293c 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -36,26 +36,18 @@
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#include <linux/vmalloc.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static char version[] __devinitdata =
- DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
-#endif
-
MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Freescale Ethernet Driver");
MODULE_LICENSE("GPL");
@@ -738,9 +730,6 @@ static void generic_adjust_link(struct net_device *dev)
if (!fep->oldlink) {
new_state = 1;
fep->oldlink = 1;
- netif_tx_schedule_all(dev);
- netif_carrier_on(dev);
- netif_start_queue(dev);
}
if (new_state)
@@ -750,8 +739,6 @@ static void generic_adjust_link(struct net_device *dev)
fep->oldlink = 0;
fep->oldspeed = 0;
fep->oldduplex = -1;
- netif_carrier_off(dev);
- netif_stop_queue(dev);
}
if (new_state && netif_msg_link(fep))
@@ -826,6 +813,8 @@ static int fs_enet_open(struct net_device *dev)
}
phy_start(fep->phydev);
+ netif_start_queue(dev);
+
return 0;
}
@@ -958,190 +947,6 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
extern int fs_mii_connect(struct net_device *dev);
extern void fs_mii_disconnect(struct net_device *dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static struct net_device *fs_init_instance(struct device *dev,
- struct fs_platform_info *fpi)
-{
- struct net_device *ndev = NULL;
- struct fs_enet_private *fep = NULL;
- int privsize, i, r, err = 0, registered = 0;
-
- fpi->fs_no = fs_get_id(fpi);
- /* guard */
- if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
- return ERR_PTR(-EINVAL);
-
- privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
- (fpi->rx_ring + fpi->tx_ring));
-
- ndev = alloc_etherdev(privsize);
- if (!ndev) {
- err = -ENOMEM;
- goto err;
- }
-
- fep = netdev_priv(ndev);
-
- fep->dev = dev;
- dev_set_drvdata(dev, ndev);
- fep->fpi = fpi;
- if (fpi->init_ioports)
- fpi->init_ioports((struct fs_platform_info *)fpi);
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
- if (fs_get_fec_index(fpi->fs_no) >= 0)
- fep->ops = &fs_fec_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
- if (fs_get_scc_index(fpi->fs_no) >=0)
- fep->ops = &fs_scc_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
- if (fs_get_fcc_index(fpi->fs_no) >= 0)
- fep->ops = &fs_fcc_ops;
-#endif
-
- if (fep->ops == NULL) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s No matching ops found (%d).\n",
- ndev->name, fpi->fs_no);
- err = -EINVAL;
- goto err;
- }
-
- r = (*fep->ops->setup_data)(ndev);
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s setup_data failed\n",
- ndev->name);
- err = r;
- goto err;
- }
-
- /* point rx_skbuff, tx_skbuff */
- fep->rx_skbuff = (struct sk_buff **)&fep[1];
- fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
-
- /* init locks */
- spin_lock_init(&fep->lock);
- spin_lock_init(&fep->tx_lock);
-
- /*
- * Set the Ethernet address.
- */
- for (i = 0; i < 6; i++)
- ndev->dev_addr[i] = fpi->macaddr[i];
-
- r = (*fep->ops->allocate_bd)(ndev);
-
- if (fep->ring_base == NULL) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
- err = r;
- goto err;
- }
-
- /*
- * Set receive and transmit descriptor base.
- */
- fep->rx_bd_base = fep->ring_base;
- fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
-
- /* initialize ring size variables */
- fep->tx_ring = fpi->tx_ring;
- fep->rx_ring = fpi->rx_ring;
-
- /*
- * The FEC Ethernet specific entries in the device structure.
- */
- ndev->open = fs_enet_open;
- ndev->hard_start_xmit = fs_enet_start_xmit;
- ndev->tx_timeout = fs_timeout;
- ndev->watchdog_timeo = 2 * HZ;
- ndev->stop = fs_enet_close;
- ndev->get_stats = fs_enet_get_stats;
- ndev->set_multicast_list = fs_set_multicast_list;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- ndev->poll_controller = fs_enet_netpoll;
-#endif
-
- netif_napi_add(ndev, &fep->napi,
- fs_enet_rx_napi, fpi->napi_weight);
-
- ndev->ethtool_ops = &fs_ethtool_ops;
- ndev->do_ioctl = fs_ioctl;
-
- init_timer(&fep->phy_timer_list);
-
- netif_carrier_off(ndev);
-
- err = register_netdev(ndev);
- if (err != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- ": %s register_netdev failed.\n", ndev->name);
- goto err;
- }
- registered = 1;
-
-
- return ndev;
-
-err:
- if (ndev != NULL) {
- if (registered)
- unregister_netdev(ndev);
-
- if (fep && fep->ops) {
- (*fep->ops->free_bd)(ndev);
- (*fep->ops->cleanup_data)(ndev);
- }
-
- free_netdev(ndev);
- }
-
- dev_set_drvdata(dev, NULL);
-
- return ERR_PTR(err);
-}
-
-static int fs_cleanup_instance(struct net_device *ndev)
-{
- struct fs_enet_private *fep;
- const struct fs_platform_info *fpi;
- struct device *dev;
-
- if (ndev == NULL)
- return -EINVAL;
-
- fep = netdev_priv(ndev);
- if (fep == NULL)
- return -EINVAL;
-
- fpi = fep->fpi;
-
- unregister_netdev(ndev);
-
- dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
- (void __force *)fep->ring_base, fep->ring_mem_addr);
-
- /* reset it */
- (*fep->ops->cleanup_data)(ndev);
-
- dev = fep->dev;
- if (dev != NULL) {
- dev_set_drvdata(dev, NULL);
- fep->dev = NULL;
- }
-
- free_netdev(ndev);
-
- return 0;
-}
-#endif
-
/**************************************************************************************/
/* handy pointer to the immap */
@@ -1168,7 +973,6 @@ static void cleanup_immap(void)
/**************************************************************************************/
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static int __devinit find_phy(struct device_node *np,
struct fs_platform_info *fpi)
{
@@ -1408,121 +1212,6 @@ static void __exit fs_cleanup(void)
of_unregister_platform_driver(&fs_enet_driver);
cleanup_immap();
}
-#else
-static int __devinit fs_enet_probe(struct device *dev)
-{
- struct net_device *ndev;
-
- /* no fixup - no device */
- if (dev->platform_data == NULL) {
- printk(KERN_INFO "fs_enet: "
- "probe called with no platform data; "
- "remove unused devices\n");
- return -ENODEV;
- }
-
- ndev = fs_init_instance(dev, dev->platform_data);
- if (IS_ERR(ndev))
- return PTR_ERR(ndev);
- return 0;
-}
-
-static int fs_enet_remove(struct device *dev)
-{
- return fs_cleanup_instance(dev_get_drvdata(dev));
-}
-
-static struct device_driver fs_enet_fec_driver = {
- .name = "fsl-cpm-fec",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static struct device_driver fs_enet_scc_driver = {
- .name = "fsl-cpm-scc",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static struct device_driver fs_enet_fcc_driver = {
- .name = "fsl-cpm-fcc",
- .bus = &platform_bus_type,
- .probe = fs_enet_probe,
- .remove = fs_enet_remove,
-#ifdef CONFIG_PM
-/* .suspend = fs_enet_suspend, TODO */
-/* .resume = fs_enet_resume, TODO */
-#endif
-};
-
-static int __init fs_init(void)
-{
- int r;
-
- printk(KERN_INFO
- "%s", version);
-
- r = setup_immap();
- if (r != 0)
- return r;
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
- /* let's insert mii stuff */
- r = fs_enet_mdio_bb_init();
-
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "BB PHY init failed.\n");
- return r;
- }
- r = driver_register(&fs_enet_fcc_driver);
- if (r != 0)
- goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
- r = fs_enet_mdio_fec_init();
- if (r != 0) {
- printk(KERN_ERR DRV_MODULE_NAME
- "FEC PHY init failed.\n");
- return r;
- }
-
- r = driver_register(&fs_enet_fec_driver);
- if (r != 0)
- goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
- r = driver_register(&fs_enet_scc_driver);
- if (r != 0)
- goto err;
-#endif
-
- return 0;
-err:
- cleanup_immap();
- return r;
-}
-
-static void __exit fs_cleanup(void)
-{
- driver_unregister(&fs_enet_fec_driver);
- driver_unregister(&fs_enet_fcc_driver);
- driver_unregister(&fs_enet_scc_driver);
- cleanup_immap();
-}
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
static void fs_enet_netpoll(struct net_device *dev)
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e05389c49bb..db46d2e7232 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -138,10 +138,6 @@ struct fs_enet_private {
};
/***************************************************************************/
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-int fs_enet_mdio_bb_init(void);
-int fs_enet_mdio_fec_init(void);
-#endif
void fs_init_bds(struct net_device *dev);
void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8268b3535b3..0a97fc2d97e 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -33,6 +33,7 @@
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/phy.h>
+#include <linux/of_device.h>
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
@@ -42,10 +43,6 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
@@ -87,7 +84,6 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
struct fs_platform_info *fpi = fep->fpi;
int ret = -EINVAL;
@@ -125,44 +121,6 @@ out_fccp:
iounmap(fep->fcc.fccp);
out:
return ret;
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq(pdev, 0);
- if (fep->interrupt < 0)
- return -EINVAL;
-
- /* Attach the memory for the FCC Parameter RAM */
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
- fep->fcc.ep = ioremap(r->start, r->end - r->start + 1);
- if (fep->fcc.ep == NULL)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
- fep->fcc.fccp = ioremap(r->start, r->end - r->start + 1);
- if (fep->fcc.fccp == NULL)
- return -EINVAL;
-
- if (fep->fpi->fcc_regs_c) {
- fep->fcc.fcccp = (void __iomem *)fep->fpi->fcc_regs_c;
- } else {
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "fcc_regs_c");
- fep->fcc.fcccp = ioremap(r->start,
- r->end - r->start + 1);
- }
-
- if (fep->fcc.fcccp == NULL)
- return -EINVAL;
-
- fep->fcc.mem = (void __iomem *)fep->fpi->mem_offset;
- if (fep->fcc.mem == NULL)
- return -EINVAL;
-
- return 0;
-#endif
}
#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB)
@@ -173,17 +131,6 @@ out:
static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- struct fs_platform_info *fpi = fep->fpi;
-
- fpi->cp_command = (fpi->cp_page << 26) |
- (fpi->cp_block << 21) |
- (12 << 6);
-
- fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
- if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */
- return -EINVAL;
-#endif
if (do_pd_setup(fep) != 0)
return -EINVAL;
@@ -304,9 +251,6 @@ static void restart(struct net_device *dev)
fcc_enet_t __iomem *ep = fep->fcc.ep;
dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
u16 paddrh, paddrm, paddrl;
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- u16 mem_addr;
-#endif
const unsigned char *mac;
int i;
@@ -338,19 +282,10 @@ static void restart(struct net_device *dev)
* this area.
*/
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
W16(ep, fen_genfcc.fcc_riptr, fpi->dpram_offset);
W16(ep, fen_genfcc.fcc_tiptr, fpi->dpram_offset + 32);
W16(ep, fen_padptr, fpi->dpram_offset + 64);
-#else
- mem_addr = (u32) fep->fcc.mem; /* de-fixup dpram offset */
-
- W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
- W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
-
- W16(ep, fen_padptr, mem_addr + 64);
-#endif
/* fill with special symbol... */
memset_io(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 8a311d1e435..0a7d1c5c652 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -32,6 +32,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -43,10 +44,6 @@
#include <asm/cpm1.h>
#endif
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
#include "fs_enet.h"
#include "fec.h"
@@ -99,7 +96,6 @@ static int whack_reset(fec_t __iomem *fecp)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -111,23 +107,6 @@ static int do_pd_setup(struct fs_enet_private *fep)
return -EINVAL;
return 0;
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
- if (fep->interrupt < 0)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->fec.fecp = ioremap(r->start, r->end - r->start + 1);
-
- if(fep->fec.fecp == NULL)
- return -EINVAL;
-
- return 0;
-#endif
}
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index e3557eca7b6..029b3c7ef29 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -32,6 +32,7 @@
#include <linux/bitops.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -43,10 +44,6 @@
#include <asm/cpm1.h>
#endif
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
/*************************************************/
@@ -99,7 +96,6 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
static int do_pd_setup(struct fs_enet_private *fep)
{
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
struct of_device *ofdev = to_of_device(fep->dev);
fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -115,27 +111,6 @@ static int do_pd_setup(struct fs_enet_private *fep)
iounmap(fep->scc.sccp);
return -EINVAL;
}
-#else
- struct platform_device *pdev = to_platform_device(fep->dev);
- struct resource *r;
-
- /* Fill out IRQ field */
- fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
- if (fep->interrupt < 0)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- fep->scc.sccp = ioremap(r->start, r->end - r->start + 1);
-
- if (fep->scc.sccp == NULL)
- return -EINVAL;
-
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
- fep->scc.ep = ioremap(r->start, r->end - r->start + 1);
-
- if (fep->scc.ep == NULL)
- return -EINVAL;
-#endif
return 0;
}
@@ -149,16 +124,6 @@ static int setup_data(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
- struct fs_platform_info *fpi = fep->fpi;
-
- fep->scc.idx = fs_get_scc_index(fpi->fs_no);
- if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
- return -EINVAL;
-
- fpi->cp_command = fep->fcc.idx << 6;
-#endif
-
do_pd_setup(fep);
fep->scc.hthi = 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 1620030cd33..be4b72f4f49 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -22,10 +22,7 @@
#include <linux/mii.h>
#include <linux/platform_device.h>
#include <linux/mdio-bitbang.h>
-
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
#include <linux/of_platform.h>
-#endif
#include "fs_enet.h"
@@ -110,7 +107,6 @@ static struct mdiobb_ops bb_ops = {
.get_mdio_data = mdio_read,
};
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
struct device_node *np)
{
@@ -271,106 +267,3 @@ static void fs_enet_mdio_bb_exit(void)
module_init(fs_enet_mdio_bb_init);
module_exit(fs_enet_mdio_bb_exit);
-#else
-static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
- struct fs_mii_bb_platform_info *fmpi)
-{
- bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
- bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
- bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
- bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
-
- return 0;
-}
-
-static int __devinit fs_enet_mdio_probe(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fs_mii_bb_platform_info *pdata;
- struct mii_bus *new_bus;
- struct bb_info *bitbang;
- int err = 0;
-
- if (NULL == dev)
- return -EINVAL;
-
- bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
-
- if (NULL == bitbang)
- return -ENOMEM;
-
- bitbang->ctrl.ops = &bb_ops;
-
- new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
-
- if (NULL == new_bus)
- return -ENOMEM;
-
- new_bus->name = "BB MII Bus",
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- new_bus->phy_mask = ~0x9;
- pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- /*set up workspace*/
- fs_mii_bitbang_init(bitbang, pdata);
-
- new_bus->priv = bitbang;
-
- new_bus->irq = pdata->irq;
-
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
-
- err = mdiobus_register(new_bus);
-
- if (0 != err) {
- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
- new_bus->name);
- goto bus_register_fail;
- }
-
- return 0;
-
-bus_register_fail:
- free_mdio_bitbang(new_bus);
- kfree(bitbang);
-
- return err;
-}
-
-static int fs_enet_mdio_remove(struct device *dev)
-{
- struct mii_bus *bus = dev_get_drvdata(dev);
-
- mdiobus_unregister(bus);
-
- dev_set_drvdata(dev, NULL);
-
- free_mdio_bitbang(bus);
-
- return 0;
-}
-
-static struct device_driver fs_enet_bb_mdio_driver = {
- .name = "fsl-bb-mdio",
- .bus = &platform_bus_type,
- .probe = fs_enet_mdio_probe,
- .remove = fs_enet_mdio_remove,
-};
-
-int fs_enet_mdio_bb_init(void)
-{
- return driver_register(&fs_enet_bb_mdio_driver);
-}
-
-void fs_enet_mdio_bb_exit(void)
-{
- driver_unregister(&fs_enet_bb_mdio_driver);
-}
-#endif
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 8f6a43b0e0f..695f74cc439 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -31,15 +31,12 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
#include "fs_enet.h"
#include "fec.h"
@@ -51,52 +48,6 @@
#define FEC_MII_LOOPS 10000
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static int match_has_phy (struct device *dev, void* data)
-{
- struct platform_device* pdev = container_of(dev, struct platform_device, dev);
- struct fs_platform_info* fpi;
- if(strcmp(pdev->name, (char*)data))
- {
- return 0;
- }
-
- fpi = pdev->dev.platform_data;
- if((fpi)&&(fpi->has_phy))
- return 1;
- return 0;
-}
-
-static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
-{
- struct resource *r;
- fec_t __iomem *fecp;
- char* name = "fsl-cpm-fec";
-
- /* we need fec in order to be useful */
- struct platform_device *fec_pdev =
- container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
- struct platform_device, dev);
-
- if(fec_pdev == NULL) {
- printk(KERN_ERR"Unable to find PHY for %s", name);
- return -ENODEV;
- }
-
- r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
-
- fec->fecp = fecp = ioremap(r->start,sizeof(fec_t));
- fec->mii_speed = fmpi->mii_speed;
-
- setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
- setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
- out_be32(&fecp->fec_ievent, FEC_ENET_MII);
- out_be32(&fecp->fec_mii_speed, fec->mii_speed);
-
- return 0;
-}
-#endif
-
static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
{
struct fec_info* fec = bus->priv;
@@ -151,7 +102,6 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
return 0;
}
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
{
const u32 *data;
@@ -286,95 +236,3 @@ static void fs_enet_mdio_fec_exit(void)
module_init(fs_enet_mdio_fec_init);
module_exit(fs_enet_mdio_fec_exit);
-#else
-static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fs_mii_fec_platform_info *pdata;
- struct mii_bus *new_bus;
- struct fec_info *fec;
- int err = 0;
- if (NULL == dev)
- return -EINVAL;
- new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
- if (NULL == new_bus)
- return -ENOMEM;
-
- fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
-
- if (NULL == fec)
- return -ENOMEM;
-
- new_bus->name = "FEC MII Bus",
- new_bus->read = &fs_enet_fec_mii_read,
- new_bus->write = &fs_enet_fec_mii_write,
- new_bus->reset = &fs_enet_fec_mii_reset,
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- /*set up workspace*/
-
- fs_mii_fec_init(fec, pdata);
- new_bus->priv = fec;
-
- new_bus->irq = pdata->irq;
-
- new_bus->dev = dev;
- dev_set_drvdata(dev, new_bus);
-
- err = mdiobus_register(new_bus);
-
- if (0 != err) {
- printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
- new_bus->name);
- goto bus_register_fail;
- }
-
- return 0;
-
-bus_register_fail:
- kfree(new_bus);
-
- return err;
-}
-
-
-static int fs_enet_fec_mdio_remove(struct device *dev)
-{
- struct mii_bus *bus = dev_get_drvdata(dev);
-
- mdiobus_unregister(bus);
-
- dev_set_drvdata(dev, NULL);
- kfree(bus->priv);
-
- bus->priv = NULL;
- kfree(bus);
-
- return 0;
-}
-
-static struct device_driver fs_enet_fec_mdio_driver = {
- .name = "fsl-cpm-fec-mdio",
- .bus = &platform_bus_type,
- .probe = fs_enet_fec_mdio_probe,
- .remove = fs_enet_fec_mdio_remove,
-};
-
-int fs_enet_mdio_fec_init(void)
-{
- return driver_register(&fs_enet_fec_mdio_driver);
-}
-
-void fs_enet_mdio_fec_exit(void)
-{
- driver_unregister(&fs_enet_fec_mdio_driver);
-}
-#endif
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 45a63172852..b8394cf134e 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -134,6 +134,9 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
void gfar_halt(struct net_device *dev);
+#ifdef CONFIG_PM
+static void gfar_halt_nodisable(struct net_device *dev);
+#endif
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
@@ -207,6 +210,7 @@ static int gfar_probe(struct platform_device *pdev)
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
+ spin_lock_init(&priv->bflock);
platform_set_drvdata(pdev, dev);
@@ -378,6 +382,103 @@ static int gfar_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ netif_device_detach(dev);
+
+ if (netif_running(dev)) {
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ gfar_halt_nodisable(dev);
+
+ /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+ tempval = gfar_read(&priv->regs->maccfg1);
+
+ tempval &= ~MACCFG1_TX_EN;
+
+ if (!magic_packet)
+ tempval &= ~MACCFG1_RX_EN;
+
+ gfar_write(&priv->regs->maccfg1, tempval);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_disable(&priv->napi);
+#endif
+
+ if (magic_packet) {
+ /* Enable interrupt on Magic Packet */
+ gfar_write(&priv->regs->imask, IMASK_MAG);
+
+ /* Enable Magic Packet mode */
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+ } else {
+ phy_stop(priv->phydev);
+ }
+ }
+
+ return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+ if (!magic_packet && priv->phydev)
+ phy_start(priv->phydev);
+
+ /* Disable Magic Packet mode, in case something
+ * else woke us up.
+ */
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval &= ~MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+
+ gfar_start(dev);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+ netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_enable(&priv->napi);
+#endif
+
+ return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
/* Reads the controller's registers to determine what interface
* connects it to the PHY.
@@ -534,8 +635,9 @@ static void init_registers(struct net_device *dev)
}
+#ifdef CONFIG_PM
/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->regs;
@@ -558,6 +660,15 @@ void gfar_halt(struct net_device *dev)
(IEVENT_GRSC | IEVENT_GTSC)))
cpu_relax();
}
+}
+#endif
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->regs;
+ u32 tempval;
/* Disable Rx and Tx */
tempval = gfar_read(&regs->maccfg1);
@@ -1725,7 +1836,6 @@ static void adjust_link(struct net_device *dev)
if (!priv->oldlink) {
new_state = 1;
priv->oldlink = 1;
- netif_tx_schedule_all(dev);
}
} else if (priv->oldlink) {
new_state = 1;
@@ -1910,7 +2020,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
u32 events = gfar_read(&priv->regs->ievent);
/* Clear IEVENT */
- gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+ gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+ /* Magic Packet is not an error. */
+ if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ (events & IEVENT_MAG))
+ events &= ~IEVENT_MAG;
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1978,6 +2093,8 @@ MODULE_ALIAS("platform:fsl-gianfar");
static struct platform_driver gfar_driver = {
.probe = gfar_probe,
.remove = gfar_remove,
+ .suspend = gfar_suspend,
+ .resume = gfar_resume,
.driver = {
.name = "fsl-gianfar",
.owner = THIS_MODULE,
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index bead71cb2b1..d59df98bd63 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -157,6 +157,7 @@ extern const char gfar_driver_version[];
#define MACCFG2_GMII 0x00000200
#define MACCFG2_HUGEFRAME 0x00000020
#define MACCFG2_LENGTHCHECK 0x00000010
+#define MACCFG2_MPEN 0x00000008
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
@@ -229,6 +230,7 @@ extern const char gfar_driver_version[];
#define IEVENT_CRL 0x00020000
#define IEVENT_XFUN 0x00010000
#define IEVENT_RXB0 0x00008000
+#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
#define IEVENT_FIR 0x00000008
@@ -241,7 +243,8 @@ extern const char gfar_driver_version[];
#define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -259,6 +262,7 @@ extern const char gfar_driver_version[];
#define IMASK_CRL 0x00020000
#define IMASK_XFUN 0x00010000
#define IMASK_RXB0 0x00008000
+#define IMASK_MAG 0x00000800
#define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080
#define IMASK_FIR 0x00000008
@@ -726,10 +730,14 @@ struct gfar_private {
unsigned int fifo_starve;
unsigned int fifo_starve_off;
+ /* Bitfield update lock */
+ spinlock_t bflock;
+
unsigned char vlan_enable:1,
rx_csum_enable:1,
extended_hash:1,
- bd_stash_en:1;
+ bd_stash_en:1,
+ wol_en:1; /* Wake-on-LAN enabled */
unsigned short padding;
unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147cc1e..fb7d3ccc0fd 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
int err = 0;
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
if (dev->flags & IFF_UP) {
- unsigned long flags;
-
/* Halt TX and RX, and process the frames which
* have already been received */
spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
stop_gfar(dev);
}
+ spin_lock_irqsave(&priv->bflock, flags);
priv->rx_csum_enable = data;
+ spin_unlock_irqrestore(&priv->bflock, flags);
if (dev->flags & IFF_UP)
err = startup_gfar(dev);
@@ -564,6 +565,38 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
priv->msg_enable = data;
}
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+ } else {
+ wol->supported = wol->wolopts = 0;
+ }
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ wol->wolopts != 0)
+ return -EINVAL;
+
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->bflock, flags);
+ priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+ spin_unlock_irqrestore(&priv->bflock, flags);
+
+ return 0;
+}
+#endif
const struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@ const struct ethtool_ops gfar_ethtool_ops = {
.set_tx_csum = gfar_set_tx_csum,
.get_msglevel = gfar_get_msglevel,
.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+ .get_wol = gfar_get_wol,
+ .set_wol = gfar_set_wol,
+#endif
};
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index b6500b2aacf..58f4b1d7bf1 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -123,6 +123,7 @@ static LIST_HEAD(bpq_devices);
* off into a separate class since they always nest.
*/
static struct lock_class_key bpq_netdev_xmit_lock_key;
+static struct lock_class_key bpq_netdev_addr_lock_key;
static void bpq_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -133,6 +134,7 @@ static void bpq_set_lockdep_class_one(struct net_device *dev,
static void bpq_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index ae9629fa688..c258a0586e6 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -88,6 +88,7 @@
static inline void append_crc_ccitt(unsigned char *buffer, int len)
{
unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
+ buffer += len;
*buffer++ = crc;
*buffer++ = crc >> 8;
}
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index c2c4f49d757..8239939554b 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -262,7 +262,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
}
outw(Perf_Page, ioaddr + HP_PAGING);
- NS8390_init(dev, 0);
+ NS8390p_init(dev, 0);
/* Leave the 8390 and HP chip reset. */
outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 8281209eded..0a8c64930ad 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -389,7 +389,7 @@ static void __init
hp_init_card(struct net_device *dev)
{
int irq = dev->irq;
- NS8390_init(dev, 0);
+ NS8390p_init(dev, 0);
outb_p(irqmap[irq&0x0f] | HP_RUN,
dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
return;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 1b7cb29fe68..b602c4dd0d1 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -385,7 +385,7 @@ static void igb_configure_msix(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *rx_ring = &adapter->rx_ring[i];
- rx_ring->buddy = 0;
+ rx_ring->buddy = NULL;
igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++);
adapter->eims_enable_mask |= rx_ring->eims_value;
if (rx_ring->itr_val)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index be7b723c924..e5f3da8468c 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -70,8 +70,6 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
board_82598 },
- {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT_DUAL_PORT),
- board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
board_82598 },
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0496d16f9de..daba82bbcb5 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -164,9 +164,7 @@ static void macb_handle_link_change(struct net_device *dev)
}
if (phydev->link != bp->link) {
- if (phydev->link)
- netif_tx_schedule_all(dev);
- else {
+ if (!phydev->link) {
bp->speed = 0;
bp->duplex = -1;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index efbc15567dd..42394505bb5 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -276,6 +276,7 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
* separate class since they always nest.
*/
static struct lock_class_key macvlan_netdev_xmit_lock_key;
+static struct lock_class_key macvlan_netdev_addr_lock_key;
#define MACVLAN_FEATURES \
(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
@@ -295,6 +296,8 @@ static void macvlan_set_lockdep_class_one(struct net_device *dev,
static void macvlan_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &macvlan_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 0b32648a213..4cb364e67dc 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -287,7 +287,7 @@ int meth_reset(struct net_device *dev)
/* Initial mode: 10 | Half-duplex | Accept normal packets */
priv->mac_ctrl = METH_ACCEPT_MCAST | METH_DEFAULT_IPG;
- if (dev->flags | IFF_PROMISC)
+ if (dev->flags & IFF_PROMISC)
priv->mac_ctrl |= METH_PROMISC;
mace->eth.mac_ctrl = priv->mac_ctrl;
diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 70dff94a8bc..04d5bc69a6f 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -67,6 +67,8 @@ enum {
CMD_STAT_BAD_INDEX = 0x0a,
/* FW image corrupted: */
CMD_STAT_BAD_NVMEM = 0x0b,
+ /* Error in ICM mapping (e.g. not enough auxiliary ICM pages to execute command): */
+ CMD_STAT_ICM_ERROR = 0x0c,
/* Attempt to modify a QP/EE which is not in the presumed state: */
CMD_STAT_BAD_QP_STATE = 0x10,
/* Bad segment parameters (Address/Size): */
@@ -119,6 +121,7 @@ static int mlx4_status_to_errno(u8 status)
[CMD_STAT_BAD_RES_STATE] = -EBADF,
[CMD_STAT_BAD_INDEX] = -EBADF,
[CMD_STAT_BAD_NVMEM] = -EFAULT,
+ [CMD_STAT_ICM_ERROR] = -ENFILE,
[CMD_STAT_BAD_QP_STATE] = -EINVAL,
[CMD_STAT_BAD_SEG_PARAM] = -EFAULT,
[CMD_STAT_REG_BOUND] = -EBUSY,
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index e141a1513f0..ea3a09aaa84 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/mlx4/cmd.h>
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 2b5006b9be6..57278224ba1 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -46,6 +46,10 @@ enum {
extern void __buggy_use_of_MLX4_GET(void);
extern void __buggy_use_of_MLX4_PUT(void);
+static int enable_qos;
+module_param(enable_qos, bool, 0444);
+MODULE_PARM_DESC(enable_qos, "Enable Quality of Service support in the HCA (default: off)");
+
#define MLX4_GET(dest, source, offset) \
do { \
void *__p = (char *) (source) + (offset); \
@@ -198,7 +202,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e
#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90
#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92
-#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x97
+#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
@@ -373,12 +377,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
}
}
- if (dev_cap->bmme_flags & 1)
- mlx4_dbg(dev, "Base MM extensions: yes "
- "(flags %d, rsvd L_Key %08x)\n",
- dev_cap->bmme_flags, dev_cap->reserved_lkey);
- else
- mlx4_dbg(dev, "Base MM extensions: no\n");
+ mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n",
+ dev_cap->bmme_flags, dev_cap->reserved_lkey);
/*
* Each UAR has 4 EQ doorbells; so if a UAR is reserved, then
@@ -737,6 +737,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 3);
+ /* Enable QoS support if module parameter set */
+ if (enable_qos)
+ *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 2);
+
/* QPC/EEC/CQC/EQC/RDMARC attributes */
MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index a0e046c149b..fbf0e22be12 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -98,7 +98,7 @@ struct mlx4_dev_cap {
int cmpt_entry_sz;
int mtt_entry_sz;
int resize_srq;
- u8 bmme_flags;
+ u32 bmme_flags;
u32 reserved_lkey;
u64 max_icm_sz;
int max_gso_sz;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index d3736013fe9..8e1d24cda1b 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -158,6 +158,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
+ dev->caps.bmme_flags = dev_cap->bmme_flags;
+ dev->caps.reserved_lkey = dev_cap->reserved_lkey;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index a4023c2dd05..78038499cff 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -118,6 +118,7 @@ struct mlx4_bitmap {
struct mlx4_buddy {
unsigned long **bits;
+ unsigned int *num_free;
int max_order;
spinlock_t lock;
};
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 03a9abcce52..a3c04c5f12c 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -47,7 +47,7 @@ struct mlx4_mpt_entry {
__be32 flags;
__be32 qpn;
__be32 key;
- __be32 pd;
+ __be32 pd_flags;
__be64 start;
__be64 length;
__be32 lkey;
@@ -61,11 +61,15 @@ struct mlx4_mpt_entry {
} __attribute__((packed));
#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
+#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
#define MLX4_MPT_FLAG_MIO (1 << 17)
#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
#define MLX4_MPT_FLAG_REGION (1 << 8)
+#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 26)
+#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
+
#define MLX4_MTT_FLAG_PRESENT 1
#define MLX4_MPT_STATUS_SW 0xF0
@@ -79,23 +83,26 @@ static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
spin_lock(&buddy->lock);
- for (o = order; o <= buddy->max_order; ++o) {
- m = 1 << (buddy->max_order - o);
- seg = find_first_bit(buddy->bits[o], m);
- if (seg < m)
- goto found;
- }
+ for (o = order; o <= buddy->max_order; ++o)
+ if (buddy->num_free[o]) {
+ m = 1 << (buddy->max_order - o);
+ seg = find_first_bit(buddy->bits[o], m);
+ if (seg < m)
+ goto found;
+ }
spin_unlock(&buddy->lock);
return -1;
found:
clear_bit(seg, buddy->bits[o]);
+ --buddy->num_free[o];
while (o > order) {
--o;
seg <<= 1;
set_bit(seg ^ 1, buddy->bits[o]);
+ ++buddy->num_free[o];
}
spin_unlock(&buddy->lock);
@@ -113,11 +120,13 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
while (test_bit(seg ^ 1, buddy->bits[order])) {
clear_bit(seg ^ 1, buddy->bits[order]);
+ --buddy->num_free[order];
seg >>= 1;
++order;
}
set_bit(seg, buddy->bits[order]);
+ ++buddy->num_free[order];
spin_unlock(&buddy->lock);
}
@@ -131,7 +140,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
GFP_KERNEL);
- if (!buddy->bits)
+ buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
+ GFP_KERNEL);
+ if (!buddy->bits || !buddy->num_free)
goto err_out;
for (i = 0; i <= buddy->max_order; ++i) {
@@ -143,6 +154,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
}
set_bit(0, buddy->bits[buddy->max_order]);
+ buddy->num_free[buddy->max_order] = 1;
return 0;
@@ -150,9 +162,10 @@ err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
kfree(buddy->bits[i]);
+err_out:
kfree(buddy->bits);
+ kfree(buddy->num_free);
-err_out:
return -ENOMEM;
}
@@ -164,6 +177,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
kfree(buddy->bits[i]);
kfree(buddy->bits);
+ kfree(buddy->num_free);
}
static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
@@ -314,21 +328,30 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
memset(mpt_entry, 0, sizeof *mpt_entry);
- mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS |
- MLX4_MPT_FLAG_MIO |
+ mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_MIO |
MLX4_MPT_FLAG_REGION |
mr->access);
mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key));
- mpt_entry->pd = cpu_to_be32(mr->pd);
+ mpt_entry->pd_flags = cpu_to_be32(mr->pd | MLX4_MPT_PD_FLAG_EN_INV);
mpt_entry->start = cpu_to_be64(mr->iova);
mpt_entry->length = cpu_to_be64(mr->size);
mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
+
if (mr->mtt.order < 0) {
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
mpt_entry->mtt_seg = 0;
- } else
+ } else {
mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
+ }
+
+ if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) {
+ /* fast register MR in free state */
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+ mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG);
+ } else {
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS);
+ }
err = mlx4_SW2HW_MPT(dev, mailbox,
key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
diff --git a/drivers/net/mlx4/pd.c b/drivers/net/mlx4/pd.c
index 3a93c5f0f7a..aa616892d09 100644
--- a/drivers/net/mlx4/pd.c
+++ b/drivers/net/mlx4/pd.c
@@ -91,6 +91,13 @@ EXPORT_SYMBOL_GPL(mlx4_uar_free);
int mlx4_init_uar_table(struct mlx4_dev *dev)
{
+ if (dev->caps.num_uars <= 128) {
+ mlx4_err(dev, "Only %d UAR pages (need more than 128)\n",
+ dev->caps.num_uars);
+ mlx4_err(dev, "Increase firmware log2_uar_bar_megabytes?\n");
+ return -ENODEV;
+ }
+
return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap,
dev->caps.num_uars, dev->caps.num_uars - 1,
max(128, dev->caps.reserved_uars));
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 83a877f3a55..8a97a0066a8 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2112,7 +2112,7 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
mv643xx_eth_irq(dev->irq, dev);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_CAUSE_EXT);
+ wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
}
#endif
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index b3981ed972b..3ab0e5289f7 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -125,7 +125,6 @@ struct myri10ge_cmd {
struct myri10ge_rx_buf {
struct mcp_kreq_ether_recv __iomem *lanai; /* lanai ptr for recv ring */
- u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */
struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */
struct myri10ge_rx_buffer_state *info;
struct page *page;
@@ -140,7 +139,6 @@ struct myri10ge_rx_buf {
struct myri10ge_tx_buf {
struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */
- u8 __iomem *wc_fifo; /* w/c send fifo address */
struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */
char *req_bytes;
struct myri10ge_tx_buffer_state *info;
@@ -332,10 +330,6 @@ MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed");
static int myri10ge_reset_recover = 1;
-static int myri10ge_wcfifo = 0;
-module_param(myri10ge_wcfifo, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled");
-
static int myri10ge_max_slices = 1;
module_param(myri10ge_max_slices, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues");
@@ -1218,14 +1212,8 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
/* copy 8 descriptors to the firmware at a time */
if ((idx & 7) == 7) {
- if (rx->wc_fifo == NULL)
- myri10ge_submit_8rx(&rx->lanai[idx - 7],
- &rx->shadow[idx - 7]);
- else {
- mb();
- myri10ge_pio_copy(rx->wc_fifo,
- &rx->shadow[idx - 7], 64);
- }
+ myri10ge_submit_8rx(&rx->lanai[idx - 7],
+ &rx->shadow[idx - 7]);
}
}
}
@@ -2229,18 +2217,6 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
(mgp->sram + cmd.data0);
- if (myri10ge_wcfifo && mgp->wc_enabled) {
- ss->tx.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_SEND_4 + 64 * slice;
- ss->rx_small.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_RECV_SMALL + 64 * slice;
- ss->rx_big.wc_fifo = (u8 __iomem *)
- mgp->sram + MXGEFW_ETH_RECV_BIG + 64 * slice;
- } else {
- ss->tx.wc_fifo = NULL;
- ss->rx_small.wc_fifo = NULL;
- ss->rx_big.wc_fifo = NULL;
- }
return status;
}
@@ -2573,27 +2549,6 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
mb();
}
-static inline void
-myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
- struct mcp_kreq_ether_send *src, int cnt)
-{
- tx->req += cnt;
- mb();
- while (cnt >= 4) {
- myri10ge_pio_copy(tx->wc_fifo, src, 64);
- mb();
- src += 4;
- cnt -= 4;
- }
- if (cnt > 0) {
- /* pad it to 64 bytes. The src is 64 bytes bigger than it
- * needs to be so that we don't overrun it */
- myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt),
- src, 64);
- mb();
- }
-}
-
/*
* Transmit a packet. We need to split the packet so that a single
* segment does not cross myri10ge->tx_boundary, so this makes segment
@@ -2830,10 +2785,7 @@ again:
MXGEFW_FLAGS_FIRST)));
idx = ((count - 1) + tx->req) & tx->mask;
tx->info[idx].last = 1;
- if (tx->wc_fifo == NULL)
- myri10ge_submit_req(tx, tx->req_list, count);
- else
- myri10ge_submit_req_wc(tx, tx->req_list, count);
+ myri10ge_submit_req(tx, tx->req_list, count);
tx->pkt_start++;
if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
tx->stop_queue++;
@@ -3768,14 +3720,14 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (mgp->sram_size > mgp->board_span) {
dev_err(&pdev->dev, "board span %ld bytes too small\n",
mgp->board_span);
- goto abort_with_wc;
+ goto abort_with_mtrr;
}
- mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+ mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
if (mgp->sram == NULL) {
dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
mgp->board_span, mgp->iomem_base);
status = -ENXIO;
- goto abort_with_wc;
+ goto abort_with_mtrr;
}
memcpy_fromio(mgp->eeprom_strings,
mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
@@ -3876,7 +3828,7 @@ abort_with_firmware:
abort_with_ioremap:
iounmap(mgp->sram);
-abort_with_wc:
+abort_with_mtrr:
#ifdef CONFIG_MTRR
if (mgp->mtrr >= 0)
mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 14126973bd1..2fec6122c7f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -355,7 +355,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
}
/* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
+ We must first initialize registers, similar to NS8390p_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
{
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 8f725634692..332df75a9ab 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -404,7 +404,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
/* Read the 16 bytes of station address PROM.
We must first initialize registers, similar to
- NS8390_init(eifdev, 0).
+ NS8390p_init(eifdev, 0).
We can't reliably read the SAPROM address without this.
(I learned the hard way!). */
{
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
index a07cdc6f738..8e7c4c910d2 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/netxen/Makefile
@@ -32,4 +32,4 @@
obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
- netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
+ netxen_nic_ethtool.o netxen_nic_niu.o netxen_nic_ctx.o
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index da4c4fb9706..8e736614407 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -54,6 +54,7 @@
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/vmalloc.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -63,10 +64,12 @@
#include "netxen_nic_hw.h"
-#define _NETXEN_NIC_LINUX_MAJOR 3
-#define _NETXEN_NIC_LINUX_MINOR 4
-#define _NETXEN_NIC_LINUX_SUBVERSION 18
-#define NETXEN_NIC_LINUX_VERSIONID "3.4.18"
+#define _NETXEN_NIC_LINUX_MAJOR 4
+#define _NETXEN_NIC_LINUX_MINOR 0
+#define _NETXEN_NIC_LINUX_SUBVERSION 0
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.0"
+
+#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#define NETXEN_NUM_FLASH_SECTORS (64)
#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -84,7 +87,7 @@
#define TX_RINGSIZE \
(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
#define RCV_BUFFSIZE \
- (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+ (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count)
#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
#define NETXEN_NETDEV_STATUS 0x1
@@ -111,6 +114,13 @@
#define NX_P2_C0 0x24
#define NX_P2_C1 0x25
+#define NX_P3_A0 0x30
+#define NX_P3_A2 0x30
+#define NX_P3_B0 0x40
+#define NX_P3_B1 0x41
+
+#define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1)
+#define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0)
#define FIRST_PAGE_GROUP_START 0
#define FIRST_PAGE_GROUP_END 0x100000
@@ -125,6 +135,16 @@
#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
+#define P2_MAX_MTU (8000)
+#define P3_MAX_MTU (9600)
+#define NX_ETHERMTU 1500
+#define NX_MAX_ETHERHDR 32 /* This contains some padding */
+
+#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU)
+#define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU)
+#define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU)
+#define NX_CT_DEFAULT_RX_BUF_LEN 2048
+
#define MAX_RX_BUFFER_LENGTH 1760
#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512)
@@ -132,7 +152,6 @@
#define RX_JUMBO_DMA_MAP_LEN \
(MAX_RX_JUMBO_BUFFER_LENGTH - 2)
#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2)
-#define NETXEN_ROM_ROUNDUP 0x80000000ULL
/*
* Maximum number of ring contexts
@@ -140,16 +159,16 @@
#define MAX_RING_CTX 1
/* Opcodes to be used with the commands */
-enum {
- TX_ETHER_PKT = 0x01,
-/* The following opcodes are for IP checksum */
- TX_TCP_PKT,
- TX_UDP_PKT,
- TX_IP_PKT,
- TX_TCP_LSO,
- TX_IPSEC,
- TX_IPSEC_CMD
-};
+#define TX_ETHER_PKT 0x01
+#define TX_TCP_PKT 0x02
+#define TX_UDP_PKT 0x03
+#define TX_IP_PKT 0x04
+#define TX_TCP_LSO 0x05
+#define TX_TCP_LSO6 0x06
+#define TX_IPSEC 0x07
+#define TX_IPSEC_CMD 0x0a
+#define TX_TCPV6_PKT 0x0b
+#define TX_UDPV6_PKT 0x0c
/* The following opcodes are for internal consumption. */
#define NETXEN_CONTROL_OP 0x10
@@ -191,6 +210,7 @@ enum {
#define MAX_RCV_DESCRIPTORS 16384
#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4)
#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4)
+#define MAX_RCV_DESCRIPTORS_10G 8192
#define MAX_JUMBO_RCV_DESCRIPTORS 1024
#define MAX_LRO_RCV_DESCRIPTORS 64
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
@@ -219,8 +239,6 @@ enum {
#define MPORT_MULTI_FUNCTION_MODE 0x2222
#include "netxen_nic_phan_reg.h"
-extern unsigned long long netxen_dma_mask;
-extern unsigned long last_schedule_time;
/*
* NetXen host-peg signal message structure
@@ -289,7 +307,7 @@ struct netxen_ring_ctx {
#define netxen_set_cmd_desc_port(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) & 0xF0))
+ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
#define netxen_set_cmd_desc_flags(cmd_desc, val) \
(cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
@@ -377,8 +395,8 @@ struct rcv_desc {
};
/* opcode field in status_desc */
-#define RCV_NIC_PKT (0xA)
-#define STATUS_NIC_PKT ((RCV_NIC_PKT) << 12)
+#define NETXEN_NIC_RXPKT_DESC 0x04
+#define NETXEN_OLD_RXPKT_DESC 0x3f
/* for status field in status_desc */
#define STATUS_NEED_CKSUM (1)
@@ -410,6 +428,8 @@ struct rcv_desc {
(((sts_data) >> 28) & 0xFFFF)
#define netxen_get_sts_prot(sts_data) \
(((sts_data) >> 44) & 0x0F)
+#define netxen_get_sts_pkt_offset(sts_data) \
+ (((sts_data) >> 48) & 0x1F)
#define netxen_get_sts_opcode(sts_data) \
(((sts_data) >> 58) & 0x03F)
@@ -424,17 +444,30 @@ struct rcv_desc {
struct status_desc {
/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
- 28-43 reference_handle, 44-47 protocol, 48-52 unused
+ 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
__le64 status_desc_data;
- __le32 hash_value;
- u8 hash_type;
- u8 msg_type;
- u8 unused;
- /* Bit pattern: 0-6 lro_count indicates frag sequence,
- 7 last_frag indicates last frag */
- u8 lro;
+ union {
+ struct {
+ __le32 hash_value;
+ u8 hash_type;
+ u8 msg_type;
+ u8 unused;
+ union {
+ /* Bit pattern: 0-6 lro_count indicates frag
+ * sequence, 7 last_frag indicates last frag
+ */
+ u8 lro;
+
+ /* chained buffers */
+ u8 nr_frags;
+ };
+ };
+ struct {
+ __le16 frag_handles[4];
+ };
+ };
} __attribute__ ((aligned(16)));
enum {
@@ -464,7 +497,20 @@ typedef enum {
NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
- NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+ NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
+
+ NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
+ NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
+ NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
+ NETXEN_BRDTYPE_P3_4_GB = 0x0024,
+ NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
+ NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
+ NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
+ NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
+ NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
+ NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
+ NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+
} netxen_brdtype_t;
typedef enum {
@@ -747,6 +793,7 @@ struct netxen_cmd_buffer {
/* In rx_buffer, we do not need multiple fragments as is a single buffer */
struct netxen_rx_buffer {
+ struct list_head list;
struct sk_buff *skb;
u64 dma;
u16 ref_handle;
@@ -765,7 +812,6 @@ struct netxen_rx_buffer {
* contains interrupt info as well shared hardware info.
*/
struct netxen_hardware_context {
- struct pci_dev *pdev;
void __iomem *pci_base0;
void __iomem *pci_base1;
void __iomem *pci_base2;
@@ -773,15 +819,20 @@ struct netxen_hardware_context {
unsigned long first_page_group_start;
void __iomem *db_base;
unsigned long db_len;
+ unsigned long pci_len0;
+
+ u8 cut_through;
+ int qdr_sn_window;
+ int ddr_mn_window;
+ unsigned long mn_win_crb;
+ unsigned long ms_win_crb;
u8 revision_id;
u16 board_type;
struct netxen_board_info boardcfg;
- u32 xg_linkup;
- u32 qg_linksup;
+ u32 linkup;
/* Address of cmd ring in Phantom */
struct cmd_desc_type0 *cmd_desc_head;
- struct pci_dev *cmd_desc_pdev;
dma_addr_t cmd_desc_phys_addr;
struct netxen_adapter *adapter;
int pci_func;
@@ -813,17 +864,17 @@ struct netxen_adapter_stats {
* Rcv Descriptor Context. One such per Rcv Descriptor. There may
* be one Rcv Descriptor for normal packets, one for jumbo and may be others.
*/
-struct netxen_rcv_desc_ctx {
+struct nx_host_rds_ring {
u32 flags;
u32 producer;
- u32 rcv_pending; /* Num of bufs posted in phantom */
dma_addr_t phys_addr;
- struct pci_dev *phys_pdev;
+ u32 crb_rcv_producer; /* reg offset */
struct rcv_desc *desc_head; /* address of rx ring in Phantom */
u32 max_rx_desc_count;
u32 dma_size;
u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
+ struct list_head free_list;
int begin_alloc;
};
@@ -834,17 +885,319 @@ struct netxen_rcv_desc_ctx {
* present elsewhere.
*/
struct netxen_recv_context {
- struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
- u32 status_rx_producer;
+ u32 state;
+ u16 context_id;
+ u16 virt_port;
+
+ struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
u32 status_rx_consumer;
+ u32 crb_sts_consumer; /* reg offset */
dma_addr_t rcv_status_desc_phys_addr;
- struct pci_dev *rcv_status_desc_pdev;
struct status_desc *rcv_status_desc_head;
};
-#define NETXEN_NIC_MSI_ENABLED 0x02
-#define NETXEN_DMA_MASK 0xfffffffe
-#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+/* New HW context creation */
+
+#define NX_OS_CRB_RETRY_COUNT 4000
+#define NX_CDRP_SIGNATURE_MAKE(pcifn, version) \
+ (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+#define NX_CDRP_CMD_GET_STATISTICS 0x0000000f
+#define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010
+#define NX_CDRP_CMD_SET_MTU 0x00000012
+#define NX_CDRP_CMD_MAX 0x00000013
+
+#define NX_RCODE_SUCCESS 0
+#define NX_RCODE_NO_HOST_MEM 1
+#define NX_RCODE_NO_HOST_RESOURCE 2
+#define NX_RCODE_NO_CARD_CRB 3
+#define NX_RCODE_NO_CARD_MEM 4
+#define NX_RCODE_NO_CARD_RESOURCE 5
+#define NX_RCODE_INVALID_ARGS 6
+#define NX_RCODE_INVALID_ACTION 7
+#define NX_RCODE_INVALID_STATE 8
+#define NX_RCODE_NOT_SUPPORTED 9
+#define NX_RCODE_NOT_PERMITTED 10
+#define NX_RCODE_NOT_READY 11
+#define NX_RCODE_DOES_NOT_EXIST 12
+#define NX_RCODE_ALREADY_EXISTS 13
+#define NX_RCODE_BAD_SIGNATURE 14
+#define NX_RCODE_CMD_NOT_IMPL 15
+#define NX_RCODE_CMD_INVALID 16
+#define NX_RCODE_TIMEOUT 17
+#define NX_RCODE_CMD_FAILED 18
+#define NX_RCODE_MAX_EXCEEDED 19
+#define NX_RCODE_MAX 20
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+/*
+ * Capabilities
+ */
+#define NX_CAP_BIT(class, bit) (1 << bit)
+#define NX_CAP0_LEGACY_CONTEXT NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO NX_CAP_BIT(0, 5)
+#define NX_CAP0_LSO NX_CAP_BIT(0, 6)
+#define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7)
+#define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8)
+
+/*
+ * Context state
+ */
+#define NX_HOST_CTX_STATE_FREED 0
+#define NX_HOST_CTX_STATE_ALLOCATED 1
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+/*
+ * Rx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u16 msi_index;
+ u16 rsvd; /* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u64 buff_size; /* Packet buffer size */
+ u32 ring_size; /* Ring entries */
+ u32 ring_kind; /* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 host_rds_crb_mode; /* RDS crb usage */
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u8 reserved[128]; /* reserve space for future expansion*/
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N hostrq_rds_rings
+ - N hostrq_sds_rings */
+ char data[0];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 rsvd1; /* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct {
+ u32 host_consumer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct {
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u32 host_ctx_state; /* Starting State */
+ u32 num_fn_per_port; /* How many PCI fn share the port */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ u8 reserved[128]; /* save space for future expansion */
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N cardrsp_rds_rings
+ - N cardrs_sds_rings */
+ char data[0];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \
+ (sizeof(HOSTRQ_RX) + \
+ (rds_rings)*(sizeof(nx_hostrq_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_hostrq_sds_ring_t)))
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \
+ (sizeof(CARDRSP_RX) + \
+ (rds_rings)*(sizeof(nx_cardrsp_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_cardrsp_sds_ring_t)))
+
+/*
+ * Tx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u32 rsvd; /* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u64 cmd_cons_dma_addr; /* */
+ u64 dummy_dma_addr; /* */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u16 interrupt_ctl;
+ u16 msi_index;
+ u16 rsvd3; /* Padding */
+ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
+ u8 reserved[128]; /* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct {
+ u32 host_ctx_state; /* Starting state */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
+ u8 reserved[128]; /* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) (sizeof(HOSTRQ_TX))
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX) (sizeof(CARDRSP_TX))
+
+/* CRB */
+
+#define NX_HOST_RDS_CRB_MODE_UNIQUE 0
+#define NX_HOST_RDS_CRB_MODE_SHARED 1
+#define NX_HOST_RDS_CRB_MODE_CUSTOM 2
+#define NX_HOST_RDS_CRB_MODE_MAX 3
+
+#define NX_HOST_INT_CRB_MODE_UNIQUE 0
+#define NX_HOST_INT_CRB_MODE_SHARED 1
+#define NX_HOST_INT_CRB_MODE_NORX 2
+#define NX_HOST_INT_CRB_MODE_NOTX 3
+#define NX_HOST_INT_CRB_MODE_NORXTX 4
+
+
+/* MAC */
+
+#define MC_COUNT_P2 16
+#define MC_COUNT_P3 38
+
+#define NETXEN_MAC_NOOP 0
+#define NETXEN_MAC_ADD 1
+#define NETXEN_MAC_DEL 2
+
+typedef struct nx_mac_list_s {
+ struct nx_mac_list_s *next;
+ uint8_t mac_addr[MAX_ADDR_LEN];
+} nx_mac_list_t;
+
+/*
+ * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
+ * adjusted based on configured MTU.
+ */
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US 3
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS 256
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS 64
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US 4
+
+#define NETXEN_NIC_INTR_DEFAULT 0x04
+
+typedef union {
+ struct {
+ uint16_t rx_packets;
+ uint16_t rx_time_us;
+ uint16_t tx_packets;
+ uint16_t tx_time_us;
+ } data;
+ uint64_t word;
+} nx_nic_intr_coalesce_data_t;
+
+typedef struct {
+ uint16_t stats_time_us;
+ uint16_t rate_sample_time;
+ uint16_t flags;
+ uint16_t rsvd_1;
+ uint32_t low_threshold;
+ uint32_t high_threshold;
+ nx_nic_intr_coalesce_data_t normal;
+ nx_nic_intr_coalesce_data_t low;
+ nx_nic_intr_coalesce_data_t high;
+ nx_nic_intr_coalesce_data_t irq;
+} nx_nic_intr_coalesce_t;
+
+typedef struct {
+ u64 qhdr;
+ u64 req_hdr;
+ u64 words[6];
+} nx_nic_req_t;
+
+typedef struct {
+ u8 op;
+ u8 tag;
+ u8 mac_addr[6];
+} nx_mac_req_t;
+
+#define MAX_PENDING_DESC_BLOCK_SIZE 64
+
+#define NETXEN_NIC_MSI_ENABLED 0x02
+#define NETXEN_NIC_MSIX_ENABLED 0x04
+#define NETXEN_IS_MSI_FAMILY(adapter) \
+ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
+
+#define MSIX_ENTRIES_PER_ADAPTER 8
+#define NETXEN_MSIX_TBL_SPACE 8192
+#define NETXEN_PCI_REG_MSIX_TBL 0x44
+
+#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
struct netxen_dummy_dma {
void *addr;
@@ -854,46 +1207,65 @@ struct netxen_dummy_dma {
struct netxen_adapter {
struct netxen_hardware_context ahw;
- struct netxen_adapter *master;
struct net_device *netdev;
struct pci_dev *pdev;
+ int pci_using_dac;
struct napi_struct napi;
struct net_device_stats net_stats;
- unsigned char mac_addr[ETH_ALEN];
int mtu;
int portnum;
u8 physical_port;
+ u16 tx_context_id;
+
+ uint8_t mc_enabled;
+ uint8_t max_mc_count;
+ nx_mac_list_t *mac_list;
+
+ struct netxen_legacy_intr_set legacy_intr;
+ u32 crb_intr_mask;
struct work_struct watchdog_task;
struct timer_list watchdog_timer;
struct work_struct tx_timeout_task;
u32 curr_window;
+ u32 crb_win;
+ rwlock_t adapter_lock;
+
+ uint64_t dma_mask;
u32 cmd_producer;
__le32 *cmd_consumer;
u32 last_cmd_consumer;
+ u32 crb_addr_cmd_producer;
+ u32 crb_addr_cmd_consumer;
u32 max_tx_desc_count;
u32 max_rx_desc_count;
u32 max_jumbo_rx_desc_count;
u32 max_lro_rx_desc_count;
+ int max_rds_rings;
+
u32 flags;
u32 irq;
int driver_mismatch;
u32 temp;
+ u32 fw_major;
+
+ u8 msix_supported;
+ u8 max_possible_rss_rings;
+ struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
struct netxen_adapter_stats stats;
- u16 portno;
u16 link_speed;
u16 link_duplex;
u16 state;
u16 link_autoneg;
int rx_csum;
int status;
- spinlock_t stats_lock;
struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */
@@ -905,25 +1277,33 @@ struct netxen_adapter {
int is_up;
struct netxen_dummy_dma dummy_dma;
+ nx_nic_intr_coalesce_t coal;
/* Context interface shared between card and host */
struct netxen_ring_ctx *ctx_desc;
- struct pci_dev *ctx_desc_pdev;
dma_addr_t ctx_desc_phys_addr;
int intr_scheme;
int msi_mode;
int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *);
- void (*handle_phy_intr) (struct netxen_adapter *);
int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
int (*set_mtu) (struct netxen_adapter *, int);
int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
- int (*unset_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
int (*init_port) (struct netxen_adapter *, int);
- void (*init_niu) (struct netxen_adapter *);
int (*stop_port) (struct netxen_adapter *);
+
+ int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
+ int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+ int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
+ int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
+ int (*pci_write_immediate)(struct netxen_adapter *, u64, u32);
+ u32 (*pci_read_immediate)(struct netxen_adapter *, u64);
+ void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
+ u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
+ unsigned long (*pci_set_window)(struct netxen_adapter *,
+ unsigned long long);
}; /* netxen_adapter structure */
/*
@@ -988,8 +1368,6 @@ int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter);
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter);
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter);
int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
__u32 * readval);
int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
@@ -998,27 +1376,61 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
/* Functions available from netxen_nic_hw.c */
int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
int netxen_nic_get_board_info(struct netxen_adapter *adapter);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
+
+int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+ unsigned long long addr);
+void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter,
+ u32 wndw);
+
+int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size);
void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
unsigned long off, int data);
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+ unsigned long long addr);
/* Functions from netxen_nic_init.c */
void netxen_free_adapter_offload(struct netxen_adapter *adapter);
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_receive_peg_ready(struct netxen_adapter *adapter);
int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
u8 *bytes, size_t size);
@@ -1032,33 +1444,43 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
int netxen_rom_se(struct netxen_adapter *adapter, int addr);
-/* Functions from netxen_nic_isr.c */
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev);
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter);
+void netxen_free_sw_resources(struct netxen_adapter *adapter);
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+
+void netxen_release_rx_buffers(struct netxen_adapter *adapter);
+void netxen_release_tx_buffers(struct netxen_adapter *adapter);
+
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
int netxen_init_firmware(struct netxen_adapter *adapter);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
void netxen_tso_check(struct netxen_adapter *adapter,
struct cmd_desc_type0 *desc, struct sk_buff *skb);
-int netxen_nic_hw_resources(struct netxen_adapter *adapter);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
u32 ringid);
int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
-void netxen_nic_set_multi(struct net_device *netdev);
+void netxen_p2_nic_set_multi(struct net_device *netdev);
+void netxen_p3_nic_set_multi(struct net_device *netdev);
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
+
+u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer);
/*
* NetXen Board information
*/
-#define NETXEN_MAX_SHORT_NAME 16
+#define NETXEN_MAX_SHORT_NAME 32
struct netxen_brdinfo {
netxen_brdtype_t brdtype; /* type of board */
long ports; /* max no of physical ports */
@@ -1072,6 +1494,17 @@ static const struct netxen_brdinfo netxen_boards[] = {
{NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"},
{NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"},
{NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"},
+ {NETXEN_BRDTYPE_P3_REF_QG, 4, "Reference Quad Gig "},
+ {NETXEN_BRDTYPE_P3_HMEZ, 2, "Dual XGb HMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_CX4_LP, 2, "Dual XGb CX4 LP"},
+ {NETXEN_BRDTYPE_P3_4_GB, 4, "Quad Gig LP"},
+ {NETXEN_BRDTYPE_P3_IMEZ, 2, "Dual XGb IMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_SFP_PLUS, 2, "Dual XGb SFP+ LP"},
+ {NETXEN_BRDTYPE_P3_10000_BASE_T, 1, "XGB 10G BaseT LP"},
+ {NETXEN_BRDTYPE_P3_XG_LOM, 2, "Dual XGb LOM"},
+ {NETXEN_BRDTYPE_P3_4_GB_MM, 4, "Quad GB - March Madness"},
+ {NETXEN_BRDTYPE_P3_10G_CX4, 2, "Reference Dual CX4 Option"},
+ {NETXEN_BRDTYPE_P3_10G_XFP, 1, "Reference Single XFP Option"}
};
#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards)
@@ -1097,7 +1530,7 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
u32 ctrl;
/* check if already inactive */
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1117,7 +1550,7 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1129,7 +1562,7 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
new file mode 100644
index 00000000000..64babc59e69
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2003 - 2008 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ * info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ */
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic.h"
+#include "netxen_nic_phan_reg.h"
+
+#define NXHAL_VERSION 1
+
+static int
+netxen_api_lock(struct netxen_adapter *adapter)
+{
+ u32 done = 0, timeout = 0;
+
+ for (;;) {
+ /* Acquire PCIE HW semaphore5 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+
+ if (done == 1)
+ break;
+
+ if (++timeout >= NX_OS_CRB_RETRY_COUNT) {
+ printk(KERN_ERR "%s: lock timeout.\n", __func__);
+ return -1;
+ }
+
+ msleep(1);
+ }
+
+#if 0
+ netxen_nic_write_w1(adapter,
+ NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
+#endif
+ return 0;
+}
+
+static int
+netxen_api_unlock(struct netxen_adapter *adapter)
+{
+ u32 val;
+
+ /* Release PCIE HW semaphore5 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+ return 0;
+}
+
+static u32
+netxen_poll_rsp(struct netxen_adapter *adapter)
+{
+ u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ int timeout = 0;
+
+ do {
+ /* give atleast 1ms for firmware to respond */
+ msleep(1);
+
+ if (++timeout > NX_OS_CRB_RETRY_COUNT)
+ return NX_CDRP_RSP_TIMEOUT;
+
+ netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
+ &raw_rsp);
+
+ rsp = le32_to_cpu(raw_rsp);
+ } while (!NX_CDRP_IS_RSP(rsp));
+
+ return rsp;
+}
+
+static u32
+netxen_issue_cmd(struct netxen_adapter *adapter,
+ u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+{
+ u32 rsp;
+ u32 signature = 0;
+ u32 rcode = NX_RCODE_SUCCESS;
+
+ signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
+
+ /* Acquire semaphore before accessing CRB */
+ if (netxen_api_lock(adapter))
+ return NX_RCODE_TIMEOUT;
+
+ netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
+ cpu_to_le32(signature));
+
+ netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
+ cpu_to_le32(arg1));
+
+ netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
+ cpu_to_le32(arg2));
+
+ netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
+ cpu_to_le32(arg3));
+
+ netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
+ cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+
+ rsp = netxen_poll_rsp(adapter);
+
+ if (rsp == NX_CDRP_RSP_TIMEOUT) {
+ printk(KERN_ERR "%s: card response timeout.\n",
+ netxen_nic_driver_name);
+
+ rcode = NX_RCODE_TIMEOUT;
+ } else if (rsp == NX_CDRP_RSP_FAIL) {
+ netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+ rcode = le32_to_cpu(rcode);
+
+ printk(KERN_ERR "%s: failed card response code:0x%x\n",
+ netxen_nic_driver_name, rcode);
+ }
+
+ /* Release semaphore */
+ netxen_api_unlock(adapter);
+
+ return rcode;
+}
+
+u32
+nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu)
+{
+ u32 rcode = NX_RCODE_SUCCESS;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
+ rcode = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ mtu,
+ 0,
+ NX_CDRP_CMD_SET_MTU);
+
+ return rcode;
+}
+
+static int
+nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
+{
+ void *addr;
+ nx_hostrq_rx_ctx_t *prq;
+ nx_cardrsp_rx_ctx_t *prsp;
+ nx_hostrq_rds_ring_t *prq_rds;
+ nx_hostrq_sds_ring_t *prq_sds;
+ nx_cardrsp_rds_ring_t *prsp_rds;
+ nx_cardrsp_sds_ring_t *prsp_sds;
+ struct nx_host_rds_ring *rds_ring;
+
+ dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
+ u64 phys_addr;
+
+ int i, nrds_rings, nsds_rings;
+ size_t rq_size, rsp_size;
+ u32 cap, reg;
+
+ int err;
+
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ /* only one sds ring for now */
+ nrds_rings = adapter->max_rds_rings;
+ nsds_rings = 1;
+
+ rq_size =
+ SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
+ rsp_size =
+ SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &hostrq_phys_addr);
+ if (addr == NULL)
+ return -ENOMEM;
+ prq = (nx_hostrq_rx_ctx_t *)addr;
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &cardrsp_phys_addr);
+ if (addr == NULL) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ prsp = (nx_cardrsp_rx_ctx_t *)addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
+
+ cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+ cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+
+ prq->capabilities[0] = cpu_to_le32(cap);
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+ prq->host_rds_crb_mode =
+ cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE);
+
+ prq->num_rds_rings = cpu_to_le16(nrds_rings);
+ prq->num_sds_rings = cpu_to_le16(nsds_rings);
+ prq->rds_ring_offset = 0;
+ prq->sds_ring_offset = prq->rds_ring_offset +
+ (sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+
+ prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+
+ for (i = 0; i < nrds_rings; i++) {
+
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
+ prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count);
+ prq_rds[i].ring_kind = cpu_to_le32(i);
+ prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
+ }
+
+ prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+
+ prq_sds[0].host_phys_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
+ /* only one msix vector for now */
+ prq_sds[0].msi_index = cpu_to_le32(0);
+
+ /* now byteswap offsets */
+ prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
+ prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+
+ phys_addr = hostrq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ (u32)(phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_RX_CTX);
+ if (err) {
+ printk(KERN_WARNING
+ "Failed to create rx ctx in firmware%d\n", err);
+ goto out_free_rsp;
+ }
+
+
+ prsp_rds = ((nx_cardrsp_rds_ring_t *)
+ &prsp->data[prsp->rds_ring_offset]);
+
+ for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
+ rds_ring->crb_rcv_producer = NETXEN_NIC_REG(reg - 0x200);
+ }
+
+ prsp_sds = ((nx_cardrsp_sds_ring_t *)
+ &prsp->data[prsp->sds_ring_offset]);
+ reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
+ recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
+
+ reg = le32_to_cpu(prsp_sds[0].interrupt_crb);
+ adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+
+ recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
+ recv_ctx->context_id = le16_to_cpu(prsp->context_id);
+ recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+
+out_free_rsp:
+ pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr);
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_RX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy rx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+static int
+nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
+{
+ nx_hostrq_tx_ctx_t *prq;
+ nx_hostrq_cds_ring_t *prq_cds;
+ nx_cardrsp_tx_ctx_t *prsp;
+ void *rq_addr, *rsp_addr;
+ size_t rq_size, rsp_size;
+ u32 temp;
+ int err = 0;
+ u64 offset, phys_addr;
+ dma_addr_t rq_phys_addr, rsp_phys_addr;
+
+ rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
+ rq_addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &rq_phys_addr);
+ if (!rq_addr)
+ return -ENOMEM;
+
+ rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
+ rsp_addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &rsp_phys_addr);
+ if (!rsp_addr) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+
+ memset(rq_addr, 0, rq_size);
+ prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+
+ memset(rsp_addr, 0, rsp_size);
+ prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
+
+ temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO);
+ prq->capabilities[0] = cpu_to_le32(temp);
+
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+
+ prq->interrupt_ctl = 0;
+ prq->msi_index = 0;
+
+ prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
+
+ offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+ prq->cmd_cons_dma_addr = cpu_to_le64(offset);
+
+ prq_cds = &prq->cds_ring;
+
+ prq_cds->host_phys_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+
+ prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count);
+
+ phys_addr = rq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ ((u32)phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_TX_CTX);
+
+ if (err == NX_RCODE_SUCCESS) {
+ temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
+ adapter->crb_addr_cmd_producer =
+ NETXEN_NIC_REG(temp - 0x200);
+#if 0
+ adapter->tx_state =
+ le32_to_cpu(prsp->host_ctx_state);
+#endif
+ adapter->tx_context_id =
+ le16_to_cpu(prsp->context_id);
+ } else {
+ printk(KERN_WARNING
+ "Failed to create tx ctx in firmware%d\n", err);
+ err = -EIO;
+ }
+
+ pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr);
+
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr);
+
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
+{
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ adapter->tx_context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_TX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy tx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+static u64 ctx_addr_sig_regs[][3] = {
+ {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
+ {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
+ {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
+ {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+};
+
+#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
+#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
+#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
+
+#define lower32(x) ((u32)((x) & 0xffffffff))
+#define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff))
+
+static struct netxen_recv_crb recv_crb_registers[] = {
+ /* Instance 0 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x100),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x110),
+ /* LRO */
+ NETXEN_NIC_REG(0x120)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x138),
+ },
+ /* Instance 1 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x144),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x154),
+ /* LRO */
+ NETXEN_NIC_REG(0x164)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x17c),
+ },
+ /* Instance 2 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x1d8),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x1f8),
+ /* LRO */
+ NETXEN_NIC_REG(0x208)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x220),
+ },
+ /* Instance 3 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x22c),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x23c),
+ /* LRO */
+ NETXEN_NIC_REG(0x24c)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x264),
+ },
+};
+
+static int
+netxen_init_old_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+ int func_id = adapter->portnum;
+
+ adapter->ctx_desc->cmd_ring_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+ adapter->ctx_desc->cmd_ring_size =
+ cpu_to_le32(adapter->max_tx_desc_count);
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+ cpu_to_le64(rds_ring->phys_addr);
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+ cpu_to_le32(rds_ring->max_rx_desc_count);
+ }
+ adapter->ctx_desc->sts_ring_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ adapter->ctx_desc->sts_ring_size =
+ cpu_to_le32(adapter->max_rx_desc_count);
+ }
+
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
+ lower32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
+ upper32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
+ NETXEN_CTX_SIGNATURE | func_id);
+ return 0;
+}
+
+static uint32_t sw_int_mask[4] = {
+ CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
+ CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
+};
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_hardware_context *hw = &adapter->ahw;
+ u32 state = 0;
+ void *addr;
+ int err = 0;
+ int ctx, ring;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err) {
+ printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
+ state);
+ return err;
+ }
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
+ &adapter->ctx_desc_phys_addr);
+
+ if (addr == NULL) {
+ DPRINTK(ERR, "failed to allocate hw context\n");
+ return -ENOMEM;
+ }
+ memset(addr, 0, sizeof(struct netxen_ring_ctx));
+ adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
+ adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
+ adapter->ctx_desc->cmd_consumer_offset =
+ cpu_to_le64(adapter->ctx_desc_phys_addr +
+ sizeof(struct netxen_ring_ctx));
+ adapter->cmd_consumer =
+ (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
+
+ /* cmd desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ &hw->cmd_desc_phys_addr);
+
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate tx desc ring\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+
+ hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ /* rx desc ring */
+ rds_ring = &recv_ctx->rds_rings[ring];
+ addr = pci_alloc_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ &rds_ring->phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate rx "
+ "desc ring[%d]\n",
+ netxen_nic_driver_name, ring);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ rds_ring->desc_head = (struct rcv_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ rds_ring->crb_rcv_producer =
+ recv_crb_registers[adapter->portnum].
+ crb_rcv_producer[ring];
+ }
+
+ /* status desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ &recv_ctx->rcv_status_desc_phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate sts desc ring\n",
+ netxen_nic_driver_name);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ recv_ctx->crb_sts_consumer =
+ recv_crb_registers[adapter->portnum].
+ crb_sts_consumer;
+ }
+
+ if (adapter->fw_major >= 4) {
+ adapter->intr_scheme = INTR_SCHEME_PERPORT;
+ adapter->msi_mode = MSI_MODE_MULTIFUNC;
+
+ err = nx_fw_cmd_create_rx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ err = nx_fw_cmd_create_tx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ } else {
+
+ adapter->intr_scheme = adapter->pci_read_normalize(adapter,
+ CRB_NIC_CAPABILITIES_FW);
+ adapter->msi_mode = adapter->pci_read_normalize(adapter,
+ CRB_NIC_MSI_MODE_FW);
+ adapter->crb_intr_mask = sw_int_mask[adapter->portnum];
+
+ err = netxen_init_old_ctx(adapter);
+ if (err) {
+ netxen_free_hw_resources(adapter);
+ return err;
+ }
+
+ }
+
+ return 0;
+
+err_out_free:
+ netxen_free_hw_resources(adapter);
+ return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ if (adapter->fw_major >= 4) {
+ nx_fw_cmd_destroy_tx_ctx(adapter);
+ nx_fw_cmd_destroy_rx_ctx(adapter);
+ }
+
+ if (adapter->ctx_desc != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) +
+ sizeof(uint32_t),
+ adapter->ctx_desc,
+ adapter->ctx_desc_phys_addr);
+ adapter->ctx_desc = NULL;
+ }
+
+ if (adapter->ahw.cmd_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ adapter->ahw.cmd_desc_head,
+ adapter->ahw.cmd_desc_phys_addr);
+ adapter->ahw.cmd_desc_head = NULL;
+ }
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ if (rds_ring->desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ rds_ring->desc_head,
+ rds_ring->phys_addr);
+ rds_ring->desc_head = NULL;
+ }
+ }
+
+ if (recv_ctx->rcv_status_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ recv_ctx->rcv_status_desc_head,
+ recv_ctx->rcv_status_desc_phys_addr);
+ recv_ctx->rcv_status_desc_head = NULL;
+ }
+ }
+}
+
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 723487bf200..48ee06b6f4e 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -93,17 +93,21 @@ static void
netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
{
struct netxen_adapter *adapter = netdev_priv(dev);
+ unsigned long flags;
u32 fw_major = 0;
u32 fw_minor = 0;
u32 fw_build = 0;
strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ fw_major = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MAJOR);
+ fw_minor = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MINOR);
+ fw_build = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_SUB);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
@@ -159,9 +163,16 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
switch ((netxen_brdtype_t) boardinfo->board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
case NETXEN_BRDTYPE_P2_SB31_2G:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
@@ -171,12 +182,17 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
break;
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_HMEZ:
ecmd->supported |= SUPPORTED_MII;
ecmd->advertising |= ADVERTISED_MII;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
@@ -349,19 +365,18 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
struct netxen_adapter *adapter = netdev_priv(dev);
__u32 mode, *regs_buff = p;
- void __iomem *addr;
int i, window;
memset(p, 0, NETXEN_NIC_REGS_LEN);
regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
(adapter->pdev)->device;
/* which mode */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+ adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
mode = regs_buff[0];
/* Common registers to all the modes */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
- &regs_buff[2]);
+ adapter->hw_read_wx(adapter,
+ NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
/* GB/XGB Mode */
mode = (mode / 2) - 1;
window = 0;
@@ -372,9 +387,9 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
window = adapter->physical_port *
NETXEN_NIC_PORT_WINDOW;
- NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
- reg[i - 3] + window,
- &regs_buff[i]);
+ adapter->hw_read_wx(adapter,
+ niu_registers[mode].reg[i - 3] + window,
+ &regs_buff[i], 4);
}
}
@@ -398,7 +413,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
return !val;
}
} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
return (val == XG_LINK_UP) ? 0 : 1;
}
return -EIO;
@@ -427,6 +442,7 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return 0;
}
+#if 0
static int
netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 * bytes)
@@ -447,7 +463,6 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
}
printk(KERN_INFO "%s: flash unlocked. \n",
netxen_nic_driver_name);
- last_schedule_time = jiffies;
ret = netxen_flash_erase_secondary(adapter);
if (ret != FLASH_SUCCESS) {
printk(KERN_ERR "%s: Flash erase failed.\n",
@@ -497,6 +512,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
}
+#endif /* 0 */
static void
netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
@@ -508,9 +524,9 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
ring->rx_jumbo_pending = 0;
for (i = 0; i < MAX_RCV_CTX; ++i) {
ring->rx_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
ring->rx_jumbo_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
}
ring->tx_pending = adapter->max_tx_desc_count;
@@ -655,7 +671,7 @@ static int netxen_nic_reg_test(struct net_device *dev)
data_written = (u32)0xa5a5a5a5;
netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
- data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+ data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
if (data_written != data_read)
return 1;
@@ -736,6 +752,117 @@ static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
+static u32 netxen_nic_get_tso(struct net_device *dev)
+{
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
+
+ return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int netxen_nic_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ dev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ dev->features |= NETIF_F_TSO6;
+ } else
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+ return 0;
+}
+
+/*
+ * Set the coalescing parameters. Currently only normal is supported.
+ * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
+ * firmware coalescing to default.
+ */
+static int netxen_set_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ /*
+ * Return Error if unsupported values or
+ * unsupported parameters are set.
+ */
+ if (ethcoal->rx_coalesce_usecs > 0xffff ||
+ ethcoal->rx_max_coalesced_frames > 0xffff ||
+ ethcoal->tx_coalesce_usecs > 0xffff ||
+ ethcoal->tx_max_coalesced_frames > 0xffff ||
+ ethcoal->rx_coalesce_usecs_irq ||
+ ethcoal->rx_max_coalesced_frames_irq ||
+ ethcoal->tx_coalesce_usecs_irq ||
+ ethcoal->tx_max_coalesced_frames_irq ||
+ ethcoal->stats_block_coalesce_usecs ||
+ ethcoal->use_adaptive_rx_coalesce ||
+ ethcoal->use_adaptive_tx_coalesce ||
+ ethcoal->pkt_rate_low ||
+ ethcoal->rx_coalesce_usecs_low ||
+ ethcoal->rx_max_coalesced_frames_low ||
+ ethcoal->tx_coalesce_usecs_low ||
+ ethcoal->tx_max_coalesced_frames_low ||
+ ethcoal->pkt_rate_high ||
+ ethcoal->rx_coalesce_usecs_high ||
+ ethcoal->rx_max_coalesced_frames_high ||
+ ethcoal->tx_coalesce_usecs_high ||
+ ethcoal->tx_max_coalesced_frames_high)
+ return -EINVAL;
+
+ if (!ethcoal->rx_coalesce_usecs ||
+ !ethcoal->rx_max_coalesced_frames) {
+ adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
+ adapter->coal.normal.data.rx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
+ adapter->coal.normal.data.rx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
+ } else {
+ adapter->coal.flags = 0;
+ adapter->coal.normal.data.rx_time_us =
+ ethcoal->rx_coalesce_usecs;
+ adapter->coal.normal.data.rx_packets =
+ ethcoal->rx_max_coalesced_frames;
+ }
+ adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
+ adapter->coal.normal.data.tx_packets =
+ ethcoal->tx_max_coalesced_frames;
+
+ netxen_config_intr_coalesce(adapter);
+
+ return 0;
+}
+
+static int netxen_get_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
+ ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
+ ethcoal->rx_max_coalesced_frames =
+ adapter->coal.normal.data.rx_packets;
+ ethcoal->tx_max_coalesced_frames =
+ adapter->coal.normal.data.tx_packets;
+
+ return 0;
+}
+
struct ethtool_ops netxen_nic_ethtool_ops = {
.get_settings = netxen_nic_get_settings,
.set_settings = netxen_nic_set_settings,
@@ -745,17 +872,22 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_eeprom_len = netxen_nic_get_eeprom_len,
.get_eeprom = netxen_nic_get_eeprom,
+#if 0
.set_eeprom = netxen_nic_set_eeprom,
+#endif
.get_ringparam = netxen_nic_get_ringparam,
.get_pauseparam = netxen_nic_get_pauseparam,
.set_pauseparam = netxen_nic_set_pauseparam,
.set_tx_csum = ethtool_op_set_tx_csum,
.set_sg = ethtool_op_set_sg,
- .set_tso = ethtool_op_set_tso,
+ .get_tso = netxen_nic_get_tso,
+ .set_tso = netxen_nic_set_tso,
.self_test = netxen_nic_diag_test,
.get_strings = netxen_nic_get_strings,
.get_ethtool_stats = netxen_nic_get_ethtool_stats,
.get_sset_count = netxen_get_sset_count,
.get_rx_csum = netxen_nic_get_rx_csum,
.set_rx_csum = netxen_nic_set_rx_csum,
+ .get_coalesce = netxen_get_intr_coalesce,
+ .set_coalesce = netxen_set_intr_coalesce,
};
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 24d027e29c4..3ce13e451aa 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -126,7 +126,8 @@ enum {
NETXEN_HW_PEGR0_CRB_AGT_ADR,
NETXEN_HW_PEGR1_CRB_AGT_ADR,
NETXEN_HW_PEGR2_CRB_AGT_ADR,
- NETXEN_HW_PEGR3_CRB_AGT_ADR
+ NETXEN_HW_PEGR3_CRB_AGT_ADR,
+ NETXEN_HW_PEGN4_CRB_AGT_ADR
};
/* Hub 5 */
@@ -316,6 +317,8 @@ enum {
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3 \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN4 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN4_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0 \
@@ -435,6 +438,7 @@ enum {
#define NETXEN_CRB_ROMUSB \
NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_SMB NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64)
#define NETXEN_CRB_PCIX_HOST NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
@@ -446,6 +450,7 @@ enum {
#define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
#define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
#define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
+#define NETXEN_CRB_QDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SN)
#define NETXEN_CRB_PCIX_MD NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
#define NETXEN_CRB_PCIE NETXEN_CRB_PCIX_MD
@@ -461,11 +466,20 @@ enum {
#define ISR_INT_TARGET_MASK_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
#define ISR_INT_TARGET_STATUS_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
#define ISR_INT_TARGET_MASK_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_STATUS_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_MASK_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_STATUS_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_MASK_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_STATUS_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_MASK_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_STATUS_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+#define ISR_INT_TARGET_MASK_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
#define NETXEN_PCI_MAPSIZE 128
#define NETXEN_PCI_DDR_NET (0x00000000UL)
#define NETXEN_PCI_QDR_NET (0x04000000UL)
#define NETXEN_PCI_DIRECT_CRB (0x04400000UL)
+#define NETXEN_PCI_CAMQM (0x04800000UL)
#define NETXEN_PCI_CAMQM_MAX (0x04ffffffUL)
#define NETXEN_PCI_OCM0 (0x05000000UL)
#define NETXEN_PCI_OCM0_MAX (0x050fffffUL)
@@ -474,6 +488,13 @@ enum {
#define NETXEN_PCI_CRBSPACE (0x06000000UL)
#define NETXEN_PCI_128MB_SIZE (0x08000000UL)
#define NETXEN_PCI_32MB_SIZE (0x02000000UL)
+#define NETXEN_PCI_2MB_SIZE (0x00200000UL)
+
+#define NETXEN_PCI_MN_2M (0)
+#define NETXEN_PCI_MS_2M (0x80000)
+#define NETXEN_PCI_OCM0_2M (0x000c0000UL)
+#define NETXEN_PCI_CAMQM_2M_BASE (0x000ff800UL)
+#define NETXEN_PCI_CAMQM_2M_END (0x04800800UL)
#define NETXEN_CRB_CAM NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
@@ -484,7 +505,14 @@ enum {
#define NETXEN_ADDR_OCM1 (0x0000000200400000ULL)
#define NETXEN_ADDR_OCM1_MAX (0x00000002004fffffULL)
#define NETXEN_ADDR_QDR_NET (0x0000000300000000ULL)
-#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P2 (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P3 (0x0000000303ffffffULL)
+
+/*
+ * Register offsets for MN
+ */
+#define NETXEN_MIU_CONTROL (0x000)
+#define NETXEN_MIU_MN_CONTROL (NETXEN_CRB_DDR_NET+NETXEN_MIU_CONTROL)
/* 200ms delay in each loop */
#define NETXEN_NIU_PHY_WAITLEN 200000
@@ -550,6 +578,9 @@ enum {
#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018)
#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c)
+#define NETXEN_UNICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1080)
+#define NETXEN_MULTICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1100)
+
#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \
(NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \
@@ -630,16 +661,76 @@ enum {
#define NETXEN_NIU_XG1_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x80054)
#define NETXEN_NIU_XG1_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x80058)
+/* P3 802.3ap */
+#define NETXEN_NIU_AP_MAC_CONFIG_0(I) (NETXEN_CRB_NIU+0xa0000+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_CONFIG_1(I) (NETXEN_CRB_NIU+0xa0004+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_IPG_IFG(I) (NETXEN_CRB_NIU+0xa0008+(I)*0x10000)
+#define NETXEN_NIU_AP_HALF_DUPLEX_CTRL(I) (NETXEN_CRB_NIU+0xa000c+(I)*0x10000)
+#define NETXEN_NIU_AP_MAX_FRAME_SIZE(I) (NETXEN_CRB_NIU+0xa0010+(I)*0x10000)
+#define NETXEN_NIU_AP_TEST_REG(I) (NETXEN_CRB_NIU+0xa001c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CONFIG(I) (NETXEN_CRB_NIU+0xa0020+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_COMMAND(I) (NETXEN_CRB_NIU+0xa0024+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_ADDR(I) (NETXEN_CRB_NIU+0xa0028+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CTRL(I) (NETXEN_CRB_NIU+0xa002c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_STATUS(I) (NETXEN_CRB_NIU+0xa0030+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_INDICATE(I) (NETXEN_CRB_NIU+0xa0034+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_CTRL(I) (NETXEN_CRB_NIU+0xa0038+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_STATUS(I) (NETXEN_CRB_NIU+0xa003c+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_0(I) (NETXEN_CRB_NIU+0xa0040+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_1(I) (NETXEN_CRB_NIU+0xa0044+(I)*0x10000)
+
+/*
+ * Register offsets for MN
+ */
+#define MIU_CONTROL (0x000)
+#define MIU_TEST_AGT_CTRL (0x090)
+#define MIU_TEST_AGT_ADDR_LO (0x094)
+#define MIU_TEST_AGT_ADDR_HI (0x098)
+#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START 1
+#define MIU_TA_CTL_ENABLE 2
+#define MIU_TA_CTL_WRITE 4
+#define MIU_TA_CTL_BUSY 8
+
+#define SIU_TEST_AGT_CTRL (0x060)
+#define SIU_TEST_AGT_ADDR_LO (0x064)
+#define SIU_TEST_AGT_ADDR_HI (0x078)
+#define SIU_TEST_AGT_WRDATA_LO (0x068)
+#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+#define SIU_TEST_AGT_RDDATA_LO (0x070)
+#define SIU_TEST_AGT_RDDATA_HI (0x074)
+#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
+
+#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
/* XG Link status */
#define XG_LINK_UP 0x10
#define XG_LINK_DOWN 0x20
+#define XG_LINK_UP_P3 0x01
+#define XG_LINK_DOWN_P3 0x02
+#define XG_LINK_STATE_P3_MASK 0xf
+#define XG_LINK_STATE_P3(pcifn,val) \
+ (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+
#define NETXEN_CAM_RAM_BASE (NETXEN_CRB_CAM + 0x02000)
#define NETXEN_CAM_RAM(reg) (NETXEN_CAM_RAM_BASE + (reg))
#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
#define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154))
#define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158))
#define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100))
+#define NETXEN_CRB_WIN_LOCK_ID (NETXEN_CAM_RAM(0x124))
#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120))
@@ -654,30 +745,71 @@ enum {
#define PCIX_INT_VECTOR (0x10100)
#define PCIX_INT_MASK (0x10104)
-#define PCIX_MN_WINDOW_F0 (0x10200)
-#define PCIX_MN_WINDOW(_f) (PCIX_MN_WINDOW_F0 + (0x20 * (_f)))
-#define PCIX_MS_WINDOW (0x10204)
-#define PCIX_SN_WINDOW_F0 (0x10208)
-#define PCIX_SN_WINDOW(_f) (PCIX_SN_WINDOW_F0 + (0x20 * (_f)))
#define PCIX_CRB_WINDOW (0x10210)
#define PCIX_CRB_WINDOW_F0 (0x10210)
#define PCIX_CRB_WINDOW_F1 (0x10230)
#define PCIX_CRB_WINDOW_F2 (0x10250)
#define PCIX_CRB_WINDOW_F3 (0x10270)
+#define PCIX_CRB_WINDOW_F4 (0x102ac)
+#define PCIX_CRB_WINDOW_F5 (0x102bc)
+#define PCIX_CRB_WINDOW_F6 (0x102cc)
+#define PCIX_CRB_WINDOW_F7 (0x102dc)
+#define PCIE_CRB_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_CRB_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_CRB_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_MN_WINDOW (0x10200)
+#define PCIX_MN_WINDOW_F0 (0x10200)
+#define PCIX_MN_WINDOW_F1 (0x10220)
+#define PCIX_MN_WINDOW_F2 (0x10240)
+#define PCIX_MN_WINDOW_F3 (0x10260)
+#define PCIX_MN_WINDOW_F4 (0x102a0)
+#define PCIX_MN_WINDOW_F5 (0x102b0)
+#define PCIX_MN_WINDOW_F6 (0x102c0)
+#define PCIX_MN_WINDOW_F7 (0x102d0)
+#define PCIE_MN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_MN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_MN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_SN_WINDOW (0x10208)
+#define PCIX_SN_WINDOW_F0 (0x10208)
+#define PCIX_SN_WINDOW_F1 (0x10228)
+#define PCIX_SN_WINDOW_F2 (0x10248)
+#define PCIX_SN_WINDOW_F3 (0x10268)
+#define PCIX_SN_WINDOW_F4 (0x102a8)
+#define PCIX_SN_WINDOW_F5 (0x102b8)
+#define PCIX_SN_WINDOW_F6 (0x102c8)
+#define PCIX_SN_WINDOW_F7 (0x102d8)
+#define PCIE_SN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4))))
#define PCIX_TARGET_STATUS (0x10118)
+#define PCIX_TARGET_STATUS_F1 (0x10160)
+#define PCIX_TARGET_STATUS_F2 (0x10164)
+#define PCIX_TARGET_STATUS_F3 (0x10168)
+#define PCIX_TARGET_STATUS_F4 (0x10360)
+#define PCIX_TARGET_STATUS_F5 (0x10364)
+#define PCIX_TARGET_STATUS_F6 (0x10368)
+#define PCIX_TARGET_STATUS_F7 (0x1036c)
+
#define PCIX_TARGET_MASK (0x10128)
-#define PCIX_TARGET_STATUS_F1 (0x10160)
-#define PCIX_TARGET_MASK_F1 (0x10170)
-#define PCIX_TARGET_STATUS_F2 (0x10164)
-#define PCIX_TARGET_MASK_F2 (0x10174)
-#define PCIX_TARGET_STATUS_F3 (0x10168)
-#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F1 (0x10170)
+#define PCIX_TARGET_MASK_F2 (0x10174)
+#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F4 (0x10370)
+#define PCIX_TARGET_MASK_F5 (0x10374)
+#define PCIX_TARGET_MASK_F6 (0x10378)
+#define PCIX_TARGET_MASK_F7 (0x1037c)
#define PCIX_MSI_F0 (0x13000)
#define PCIX_MSI_F1 (0x13004)
#define PCIX_MSI_F2 (0x13008)
#define PCIX_MSI_F3 (0x1300c)
+#define PCIX_MSI_F4 (0x13010)
+#define PCIX_MSI_F5 (0x13014)
+#define PCIX_MSI_F6 (0x13018)
+#define PCIX_MSI_F7 (0x1301c)
#define PCIX_MSI_F(i) (0x13000+((i)*4))
#define PCIX_PS_MEM_SPACE (0x90000)
@@ -695,11 +827,102 @@ enum {
#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */
#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */
#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */
-
+#define PCIE_SEM5_LOCK (0x1c028) /* API lock */
+#define PCIE_SEM5_UNLOCK (0x1c02c) /* API unlock */
+#define PCIE_SEM6_LOCK (0x1c030) /* sw lock */
+#define PCIE_SEM6_UNLOCK (0x1c034) /* sw unlock */
+#define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */
+#define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/
+
+#define PCIE_SETUP_FUNCTION (0x12040)
+#define PCIE_SETUP_FUNCTION2 (0x12048)
#define PCIE_TGT_SPLIT_CHICKEN (0x12080)
+#define PCIE_CHICKEN3 (0x120c8)
#define PCIE_MAX_MASTER_SPLIT (0x14048)
+#define NETXEN_PORT_MODE_NONE 0
+#define NETXEN_PORT_MODE_XG 1
+#define NETXEN_PORT_MODE_GB 2
+#define NETXEN_PORT_MODE_802_3_AP 3
+#define NETXEN_PORT_MODE_AUTO_NEG 4
+#define NETXEN_PORT_MODE_AUTO_NEG_1G 5
+#define NETXEN_PORT_MODE_AUTO_NEG_XG 6
+#define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24))
+#define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198))
+
#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
+#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define PCIX_INT_VECTOR_BIT_F0 0x0080
+#define PCIX_INT_VECTOR_BIT_F1 0x0100
+#define PCIX_INT_VECTOR_BIT_F2 0x0200
+#define PCIX_INT_VECTOR_BIT_F3 0x0400
+#define PCIX_INT_VECTOR_BIT_F4 0x0800
+#define PCIX_INT_VECTOR_BIT_F5 0x1000
+#define PCIX_INT_VECTOR_BIT_F6 0x2000
+#define PCIX_INT_VECTOR_BIT_F7 0x4000
+
+struct netxen_legacy_intr_set {
+ uint32_t int_vec_bit;
+ uint32_t tgt_status_reg;
+ uint32_t tgt_mask_reg;
+ uint32_t pci_int_reg;
+};
+
+#define NX_LEGACY_INTR_CONFIG \
+{ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \
+}
+
#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index c43d06b8de9..96a3bc6426e 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -38,242 +38,262 @@
#include <net/ip.h>
-struct netxen_recv_crb recv_crb_registers[] = {
- /*
- * Instance 0.
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x100),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x104),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x108),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x10c),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x110),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x114),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x118),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x11c),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x120),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x124),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x128),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x12c),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x130),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x134),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x138),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x13c),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x140),
-
- },
- /*
- * Instance 1,
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x144),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x148),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x14c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x150),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x154),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x158),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x15c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x160),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x164),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x168),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x16c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x170),
- }
-
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x174),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x178),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x17c),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x180),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x184),
- },
- /*
- * Instance 2,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1d8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1dc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x1f0),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x1f4),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1f8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1fc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x200),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x204),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x208),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x20c),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x210),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x214),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x218),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x21c),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x220),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x224),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x228),
- },
- /*
- * Instance 3,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x22c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x230),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x234),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x238),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x23c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x240),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x244),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x248),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x24c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x250),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x254),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x258),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x25c),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x260),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x264),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x268),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x26c),
- },
+#define MASK(n) ((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define MS_WIN(addr) (addr & 0x0ffc0000)
+
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+
+#define CRB_BLK(off) ((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
+#define CRB_WINDOW_2M (0x130060)
+#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define CRB_INDIRECT_2M (0x1e0000UL)
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+ {{{0, 0, 0, 0} } }, /* 0: PCI */
+ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
+ {1, 0x0110000, 0x0120000, 0x130000},
+ {1, 0x0120000, 0x0122000, 0x124000},
+ {1, 0x0130000, 0x0132000, 0x126000},
+ {1, 0x0140000, 0x0142000, 0x128000},
+ {1, 0x0150000, 0x0152000, 0x12a000},
+ {1, 0x0160000, 0x0170000, 0x110000},
+ {1, 0x0170000, 0x0172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x01e0000, 0x01e0800, 0x122000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+ {{{0, 0, 0, 0} } }, /* 3: */
+ {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+ {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
+ {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
+ {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
+ {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x08f0000, 0x08f2000, 0x172000} } },
+ {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x09f0000, 0x09f2000, 0x176000} } },
+ {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+ {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+ {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+ {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+ {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+ {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+ {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+ {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+ {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+ {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+ {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+ {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+ {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+ {{{0, 0, 0, 0} } }, /* 23: */
+ {{{0, 0, 0, 0} } }, /* 24: */
+ {{{0, 0, 0, 0} } }, /* 25: */
+ {{{0, 0, 0, 0} } }, /* 26: */
+ {{{0, 0, 0, 0} } }, /* 27: */
+ {{{0, 0, 0, 0} } }, /* 28: */
+ {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+ {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+ {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+ {{{0} } }, /* 32: PCI */
+ {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
+ {1, 0x2110000, 0x2120000, 0x130000},
+ {1, 0x2120000, 0x2122000, 0x124000},
+ {1, 0x2130000, 0x2132000, 0x126000},
+ {1, 0x2140000, 0x2142000, 0x128000},
+ {1, 0x2150000, 0x2152000, 0x12a000},
+ {1, 0x2160000, 0x2170000, 0x110000},
+ {1, 0x2170000, 0x2172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+ {{{0} } }, /* 35: */
+ {{{0} } }, /* 36: */
+ {{{0} } }, /* 37: */
+ {{{0} } }, /* 38: */
+ {{{0} } }, /* 39: */
+ {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+ {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+ {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+ {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+ {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+ {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+ {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+ {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+ {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+ {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+ {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+ {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+ {{{0} } }, /* 52: */
+ {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+ {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+ {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+ {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+ {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+ {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+ {{{0} } }, /* 59: I2C0 */
+ {{{0} } }, /* 60: I2C1 */
+ {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
+ {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+ {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
};
-static u64 ctx_addr_sig_regs[][3] = {
- {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
- {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
- {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
- {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+static unsigned crb_hub_agt[64] =
+{
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MS,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
+ NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
+ NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SN,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_EG,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
+ NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
+ 0,
};
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
-
/* PCI Windowing for DDR regions. */
#define ADDR_IN_RANGE(addr, low, high) \
(((addr) <= (high)) && ((addr) >= (low)))
-#define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START)
-#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
#define NETXEN_MIN_MTU 64
#define NETXEN_ETH_FCS_SIZE 4
#define NETXEN_ENET_HEADER_SIZE 14
-#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
+#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
#define NETXEN_NIU_HDRSIZE (0x1 << 6)
#define NETXEN_NIU_TLRSIZE (0x1 << 5)
-#define lower32(x) ((u32)((x) & 0xffffffff))
-#define upper32(x) \
- ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
-
#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
@@ -281,10 +301,6 @@ static u64 ctx_addr_sig_regs[][3] = {
#define NETXEN_NIC_WINDOW_MARGIN 0x100000
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
-
int netxen_nic_set_mac(struct net_device *netdev, void *p)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -296,266 +312,370 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- DPRINTK(INFO, "valid ether addr\n");
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, addr->sa_data);
+ /* For P3, MAC addr is not set in NIU */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ if (adapter->macaddr_set)
+ adapter->macaddr_set(adapter, addr->sa_data);
return 0;
}
-/*
- * netxen_nic_set_multi - Multicast
- */
-void netxen_nic_set_multi(struct net_device *netdev)
+#define NETXEN_UNICAST_ADDR(port, index) \
+ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
+#define NETXEN_MCAST_ADDR(port, index) \
+ (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
+#define MAC_HI(addr) \
+ ((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
+#define MAC_LO(addr) \
+ ((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
+
+static int
+netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val |= (1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ /* add broadcast addr to filter */
+ val = 0xffffff;
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ /* add station addr to filter */
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 1)+4, val);
+
+ adapter->mc_enabled = 1;
+ return 0;
+}
+
+static int
+netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (!adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val &= ~(1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+
+ adapter->mc_enabled = 0;
+ return 0;
+}
+
+static int
+netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
+ int index, u8 *addr)
+{
+ u32 hi = 0, lo = 0;
+ u16 port = adapter->physical_port;
+
+ lo = MAC_LO(addr);
+ hi = MAC_HI(addr);
+
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index), hi);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index)+4, lo);
+
+ return 0;
+}
+
+void netxen_p2_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct dev_mc_list *mc_ptr;
+ u8 null_addr[6];
+ int index = 0;
+
+ memset(null_addr, 0, 6);
- mc_ptr = netdev->mc_list;
if (netdev->flags & IFF_PROMISC) {
- if (adapter->set_promisc)
- adapter->set_promisc(adapter,
- NETXEN_NIU_PROMISC_MODE);
- } else {
- if (adapter->unset_promisc)
- adapter->unset_promisc(adapter,
- NETXEN_NIU_NON_PROMISC_MODE);
+
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_PROMISC_MODE);
+
+ /* Full promiscuous mode */
+ netxen_nic_disable_mcast_filter(adapter);
+
+ return;
+ }
+
+ if (netdev->mc_count == 0) {
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_NON_PROMISC_MODE);
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
}
+
+ adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
+ if (netdev->flags & IFF_ALLMULTI ||
+ netdev->mc_count > adapter->max_mc_count) {
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
+ }
+
+ netxen_nic_enable_mcast_filter(adapter);
+
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
+ netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
+
+ if (index != netdev->mc_count)
+ printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
+ netxen_nic_driver_name, netdev->name);
+
+ /* Clear out remaining addresses */
+ for (; index < adapter->max_mc_count; index++)
+ netxen_nic_set_mcast_addr(adapter, index, null_addr);
}
-/*
- * netxen_nic_change_mtu - Change the Maximum Transfer Unit
- * @returns 0 on success, negative on failure
- */
-int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+ u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+ nx_mac_list_t *cur, *prev;
+
+ /* if in del_list, move it to adapter->mac_list */
+ for (cur = *del_list, prev = NULL; cur;) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+ if (prev == NULL)
+ *del_list = cur->next;
+ else
+ prev->next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ return 0;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* make sure to add each mac address only once */
+ for (cur = adapter->mac_list; cur; cur = cur->next) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+ return 0;
+ }
+ /* not in del_list, create new entry and add to add_list */
+ cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
+ if (cur == NULL) {
+ printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
+ "not work properly from now.\n", __func__);
+ return -1;
+ }
- if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
- printk(KERN_ERR "%s: %s %d is not supported.\n",
- netxen_nic_driver_name, netdev->name, mtu);
+ memcpy(cur->mac_addr, addr, ETH_ALEN);
+ cur->next = *add_list;
+ *add_list = cur;
+ return 0;
+}
+
+static int
+netxen_send_cmd_descs(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+{
+ uint32_t i, producer;
+ struct netxen_cmd_buffer *pbuf;
+ struct cmd_desc_type0 *cmd_desc;
+
+ if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
+ printk(KERN_WARNING "%s: Too many command descriptors in a "
+ "request\n", __func__);
return -EINVAL;
}
- if (adapter->set_mtu)
- adapter->set_mtu(adapter, mtu);
- netdev->mtu = mtu;
+ i = 0;
+
+ producer = adapter->cmd_producer;
+ do {
+ cmd_desc = &cmd_desc_arr[i];
+
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->mss = 0;
+ pbuf->total_length = 0;
+ pbuf->skb = NULL;
+ pbuf->cmd = 0;
+ pbuf->frag_count = 0;
+ pbuf->port = 0;
+
+ /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
+ memcpy(&adapter->ahw.cmd_desc_head[producer],
+ &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+ producer = get_next_index(producer,
+ adapter->max_tx_desc_count);
+ i++;
+
+ } while (i != nr_elements);
+
+ adapter->cmd_producer = producer;
+
+ /* write producer index to start the xmit */
+
+ netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
return 0;
}
-/*
- * check if the firmware has been downloaded and ready to run and
- * setup the address for the descriptors in the adapter
- */
-int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+#define NIC_REQUEST 0x14
+#define NETXEN_MAC_EVENT 0x1
+
+static int nx_p3_sre_macaddr_change(struct net_device *dev,
+ u8 *addr, unsigned op)
{
- struct netxen_hardware_context *hw = &adapter->ahw;
- u32 state = 0;
- void *addr;
- int loops = 0, err = 0;
- int ctx, ring;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int func_id = adapter->portnum;
-
- DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
- PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
- DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
- pci_base_offset(adapter, NETXEN_CRB_CAM));
- DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
- pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
-
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
- loops = 0;
- state = 0;
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[ctx].
- crb_rcvpeg_state));
- while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
- msleep(1);
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers
- [ctx].
- crb_rcvpeg_state));
- loops++;
- }
- if (loops >= 20) {
- printk(KERN_ERR "Rcv Peg initialization not complete:"
- "%x.\n", state);
- err = -EIO;
- return err;
- }
+ struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+ nx_nic_req_t req;
+ nx_mac_req_t mac_req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_MAC_EVENT;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+ mac_req.op = op;
+ memcpy(&mac_req.mac_addr, addr, 6);
+ req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send mac update\n");
+ return rv;
}
- adapter->intr_scheme = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
- adapter->msi_mode = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- (dma_addr_t *) & adapter->ctx_desc_phys_addr,
- &adapter->ctx_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- err = -ENOMEM;
- return err;
- }
- memset(addr, 0, sizeof(struct netxen_ring_ctx));
- adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
- adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
- adapter->ctx_desc->cmd_consumer_offset =
- cpu_to_le64(adapter->ctx_desc_phys_addr +
- sizeof(struct netxen_ring_ctx));
- adapter->cmd_consumer = (__le32 *) (((char *)addr) +
- sizeof(struct netxen_ring_ctx));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- (dma_addr_t *) & hw->cmd_desc_phys_addr,
- &adapter->ahw.cmd_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- return -ENOMEM;
- }
-
- adapter->ctx_desc->cmd_ring_addr =
- cpu_to_le64(hw->cmd_desc_phys_addr);
- adapter->ctx_desc->cmd_ring_size =
- cpu_to_le32(adapter->max_tx_desc_count);
-
- hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
-
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- addr = netxen_alloc(adapter->ahw.pdev,
- RCV_DESC_RINGSIZE,
- &rcv_desc->phys_addr,
- &rcv_desc->phys_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from "
- "pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- rcv_desc->desc_head = (struct rcv_desc *)addr;
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
- cpu_to_le64(rcv_desc->phys_addr);
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
- cpu_to_le32(rcv_desc->max_rx_desc_count);
- }
- addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
- &recv_ctx->rcv_status_desc_phys_addr,
- &recv_ctx->rcv_status_desc_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from"
- " pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
- adapter->ctx_desc->sts_ring_addr =
- cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
- adapter->ctx_desc->sts_ring_size =
- cpu_to_le32(adapter->max_rx_desc_count);
-
- }
- /* Window = 1 */
-
- writel(lower32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO(func_id)));
- writel(upper32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI(func_id)));
- writel(NETXEN_CTX_SIGNATURE | func_id,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG(func_id)));
- return err;
+ return 0;
}
-void netxen_free_hw_resources(struct netxen_adapter *adapter)
+void netxen_p3_nic_set_multi(struct net_device *netdev)
{
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ctx, ring;
-
- if (adapter->ctx_desc != NULL) {
- pci_free_consistent(adapter->ctx_desc_pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- adapter->ctx_desc,
- adapter->ctx_desc_phys_addr);
- adapter->ctx_desc = NULL;
- }
-
- if (adapter->ahw.cmd_desc_head != NULL) {
- pci_free_consistent(adapter->ahw.cmd_desc_pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- adapter->ahw.cmd_desc_head,
- adapter->ahw.cmd_desc_phys_addr);
- adapter->ahw.cmd_desc_head = NULL;
- }
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
-
- if (rcv_desc->desc_head != NULL) {
- pci_free_consistent(rcv_desc->phys_pdev,
- RCV_DESC_RINGSIZE,
- rcv_desc->desc_head,
- rcv_desc->phys_addr);
- rcv_desc->desc_head = NULL;
- }
- }
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
+ struct dev_mc_list *mc_ptr;
+ u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
- if (recv_ctx->rcv_status_desc_head != NULL) {
- pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
- STATUS_DESC_RINGSIZE,
- recv_ctx->rcv_status_desc_head,
- recv_ctx->
- rcv_status_desc_phys_addr);
- recv_ctx->rcv_status_desc_head = NULL;
+ /*
+ * Programming mac addresses will automaticly enabling L2 filtering.
+ * HW will replace timestamp with L2 conid when L2 filtering is
+ * enabled. This causes problem for LSA. Do not enabling L2 filtering
+ * until that problem is fixed.
+ */
+ if ((netdev->flags & IFF_PROMISC) ||
+ (netdev->mc_count > adapter->max_mc_count))
+ return;
+
+ del_list = adapter->mac_list;
+ adapter->mac_list = NULL;
+
+ nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
+ if (netdev->mc_count > 0) {
+ nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+ for (mc_ptr = netdev->mc_list; mc_ptr;
+ mc_ptr = mc_ptr->next) {
+ nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
+ &add_list, &del_list);
}
}
+ for (cur = del_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
+ next = cur->next;
+ kfree(cur);
+ cur = next;
+ }
+ for (cur = add_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
+ next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ cur = next;
+ }
}
-void netxen_tso_check(struct netxen_adapter *adapter,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
+#define NETXEN_CONFIG_INTR_COALESCE 3
+
+/*
+ * Send the interrupt coalescing parameter set by ethtool to the card.
+ */
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
{
- if (desc->mss) {
- desc->total_hdr_length = (sizeof(struct ethhdr) +
- ip_hdrlen(skb) + tcp_hdrlen(skb));
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
- } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
- } else {
- return;
- }
+ nx_nic_req_t req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+
+ memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send "
+ "interrupt coalescing parameters\n");
}
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
+
+ return rv;
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+
+#define MTU_FUDGE_FACTOR 100
+
+int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ int max_mtu;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ max_mtu = P3_MAX_MTU;
+ else
+ max_mtu = P2_MAX_MTU;
+
+ if (mtu > max_mtu) {
+ printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
+ netdev->name, max_mtu);
+ return -EINVAL;
+ }
+
+ if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+ netdev->mtu = mtu;
+
+ mtu += MTU_FUDGE_FACTOR;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, mtu);
+ else if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+
+ return 0;
}
int netxen_is_flash_supported(struct netxen_adapter *adapter)
@@ -632,41 +752,49 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[])
return 0;
}
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+
+static int crb_win_lock(struct netxen_adapter *adapter)
+{
+ int done = 0, timeout = 0;
+
+ while (!done) {
+ /* acquire semaphore3 from PCI HW block */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+ if (done == 1)
+ break;
+ if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+ return -1;
+ timeout++;
+ udelay(1);
+ }
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+ return 0;
+}
+
+static void crb_win_unlock(struct netxen_adapter *adapter)
+{
+ int val;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+}
+
/*
* Changes the CRB window to the specified window.
*/
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+void
+netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
{
void __iomem *offset;
u32 tmp;
int count = 0;
+ uint8_t func = adapter->ahw.pci_func;
if (adapter->curr_window == wndw)
return;
- switch(adapter->ahw.pci_func) {
- case 0:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- case 1:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F1));
- break;
- case 2:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F2));
- break;
- case 3:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F3));
- break;
- default:
- printk(KERN_INFO "Changing the window for PCI function "
- "%d\n", adapter->ahw.pci_func);
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- }
/*
* Move the CRB window.
* We need to write to the "direct access" region of PCI
@@ -675,6 +803,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
* register address is received by PCI. The direct region bypasses
* the CRB bus.
*/
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
if (wndw & 0x1)
wndw = NETXEN_WINDOW_ONE;
@@ -685,7 +815,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
while ((tmp = readl(offset)) != wndw) {
printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
"registered properly: 0x%08x.\n",
- netxen_nic_driver_name, __FUNCTION__, tmp);
+ netxen_nic_driver_name, __func__, tmp);
mdelay(1);
if (count >= 10)
break;
@@ -698,51 +828,119 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
adapter->curr_window = 0;
}
+/*
+ * Return -1 if off is not valid,
+ * 1 if window access is needed. 'off' is set to offset from
+ * CRB space in 128M pci map
+ * 0 if no window access is needed. 'off' is set to 2M addr
+ * In: 'off' is offset from base in 128M pci map
+ */
+static int
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
+ ulong *off, int len)
+{
+ unsigned long end = *off + len;
+ crb_128M_2M_sub_block_map_t *m;
+
+
+ if (*off >= NETXEN_CRB_MAX)
+ return -1;
+
+ if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+ *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ if (*off < NETXEN_PCI_CRBSPACE)
+ return -1;
+
+ *off -= NETXEN_PCI_CRBSPACE;
+ end = *off + len;
+
+ /*
+ * Try direct map
+ */
+ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+ if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+ *off = *off + m->start_2M - m->start_128M +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ /*
+ * Not in direct map, use crb window
+ */
+ return 1;
+}
+
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
+{
+ u32 win_read;
+
+ adapter->crb_win = CRB_HI(*off);
+ writel(adapter->crb_win, (void *)(CRB_WINDOW_2M +
+ adapter->ahw.pci_base0));
+ /*
+ * Read back value to make sure write has gone through before trying
+ * to use it.
+ */
+ win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0));
+ if (win_read != adapter->crb_win) {
+ printk(KERN_ERR "%s: Written crbwin (0x%x) != "
+ "Read crbwin (0x%x), off=0x%lx\n",
+ __func__, adapter->crb_win, win_read, *off);
+ }
+ *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+ (ulong)adapter->ahw.pci_base0;
+}
+
int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
- u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
- u64 off;
- void __iomem *addr;
+ u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
- size = NETXEN_FIRMWARE_LEN;
- writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+ size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 1);
for (i = 0; i < size; i++) {
- int retries = 10;
if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
return -EIO;
- off = netxen_nic_pci_set_window(adapter, memaddr);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- do {
- if (readl(addr) == data)
- break;
- msleep(100);
- writel(data, addr);
- } while (--retries);
- if (!retries) {
- printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
- netxen_nic_driver_name, memaddr);
- return -EIO;
- }
+ adapter->pci_mem_write(adapter, memaddr, &data, 4);
flashaddr += 4;
memaddr += 4;
+ cond_resched();
+ }
+ msleep(1);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+ else {
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 0);
}
- udelay(100);
- /* make sure Casper is powered on */
- writel(0x3fff,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
return 0;
}
int
-netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -750,7 +948,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
@@ -758,7 +956,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
pci_base(adapter, off), off, addr,
*(unsigned long long *)data, len);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
@@ -785,14 +983,14 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
break;
}
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
int
-netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -800,13 +998,13 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
pci_base(adapter, off), off, addr);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
switch (len) {
@@ -830,81 +1028,195 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{ /* Only for window 1 */
- void __iomem *addr;
+int
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
+
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
- pci_base(adapter, off), off, addr, val);
- writel(val, addr);
+ DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n",
+ *(unsigned long *)data, off, len);
+ switch (len) {
+ case 1:
+ writeb(*(uint8_t *)data, (void *)off);
+ break;
+ case 2:
+ writew(*(uint16_t *)data, (void *)off);
+ break;
+ case 4:
+ writel(*(uint32_t *)data, (void *)off);
+ break;
+ case 8:
+ writeq(*(uint64_t *)data, (void *)off);
+ break;
+ default:
+ DPRINTK(1, INFO,
+ "writing data %lx to offset %llx, num words=%d\n",
+ *(unsigned long *)data, off, (len>>3));
+ break;
+ }
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
}
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{ /* Only for window 1 */
- void __iomem *addr;
- int val;
+int
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
- pci_base(adapter, off), off, addr);
- val = readl(addr);
- writel(val, addr);
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
+
+ DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len);
+
+ switch (len) {
+ case 1:
+ *(uint8_t *)data = readb((void *)off);
+ break;
+ case 2:
+ *(uint16_t *)data = readw((void *)off);
+ break;
+ case 4:
+ *(uint32_t *)data = readl((void *)off);
+ break;
+ case 8:
+ *(uint64_t *)data = readq((void *)off);
+ break;
+ default:
+ break;
+ }
+ DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data);
+
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
+}
+
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
+{
+ adapter->hw_write_wx(adapter, off, &val, 4);
+}
+
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
+{
+ int val;
+ adapter->hw_read_wx(adapter, off, &val, 4);
return val;
}
/* Change the window to 0, write and change back to window 1. */
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
{
- void __iomem *addr;
-
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, index);
- writel(value, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ adapter->hw_write_wx(adapter, index, &value, 4);
}
/* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
{
- void __iomem *addr;
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
- addr = pci_base_offset(adapter, index);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+ adapter->hw_write_wx(adapter, index, &value, 4);
+}
+
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
+{
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
+
+/*
+ * check memory access boundary.
+ * used by test agent. support ddr access only for now
+ */
+static unsigned long
+netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter,
+ unsigned long long addr, int size)
+{
+ if (!ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+ !ADDR_IN_RANGE(addr+size-1,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+ ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
+ return 0;
+ }
- netxen_nic_pci_change_crbwindow(adapter, 0);
- *value = readl(addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ return 1;
}
static int netxen_pci_set_window_warning_count;
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr)
+unsigned long
+netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+ unsigned long long addr)
{
- static int ddr_mn_window = -1;
- static int qdr_sn_window = -1;
+ void __iomem *offset;
int window;
+ unsigned long long qdr_max;
+ uint8_t func = adapter->ahw.pci_func;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+ } else {
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+ }
if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
/* DDR network side */
addr -= NETXEN_ADDR_DDR_NET;
window = (addr >> 25) & 0x3ff;
- if (ddr_mn_window != window) {
- ddr_mn_window = window;
- writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.ddr_mn_window != window) {
+ adapter->ahw.ddr_mn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func)));
+ writel(window, offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * NETXEN_WINDOW_ONE);
addr += NETXEN_PCI_DDR_NET;
@@ -914,22 +1226,17 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
addr -= NETXEN_ADDR_OCM1;
addr += NETXEN_PCI_OCM1;
- } else
- if (ADDR_IN_RANGE
- (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
/* QDR network side */
addr -= NETXEN_ADDR_QDR_NET;
window = (addr >> 22) & 0x3f;
- if (qdr_sn_window != window) {
- qdr_sn_window = window;
- writel((window << 22),
- PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.qdr_sn_window != window) {
+ adapter->ahw.qdr_sn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func)));
+ writel((window << 22), offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * 0x400000);
addr += NETXEN_PCI_QDR_NET;
@@ -943,11 +1250,711 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
printk("%s: Warning:netxen_nic_pci_set_window()"
" Unknown address range!\n",
netxen_nic_driver_name);
+ addr = -1UL;
+ }
+ return addr;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl((void __iomem *)(pci_base_offset(adapter, off)));
+}
+
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl(NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+unsigned long
+netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ int window;
+ u32 win_read;
+
+ if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ window = MN_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read << 17) != window) {
+ printk(KERN_INFO "Written MNwin (0x%x) != "
+ "Read MNwin (0x%x)\n", window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET;
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ if ((addr & 0x00ff800) == 0xff800) {
+ printk("%s: QM access not handled.\n", __func__);
+ addr = -1UL;
+ }
+
+ window = OCM_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read >> 7) != window) {
+ printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
+ "Read OCMwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M;
+
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) {
+ /* QDR network side */
+ window = MS_WIN(addr);
+ adapter->ahw.qdr_sn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if (win_read != window) {
+ printk(KERN_INFO "%s: Written MSwin (0x%x) != "
+ "Read MSwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET;
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((netxen_pci_set_window_warning_count++ < 8)
+ || (netxen_pci_set_window_warning_count%64 == 0)) {
+ printk("%s: Warning:%s Unknown address range!\n",
+ __func__, netxen_nic_driver_name);
+}
+ addr = -1UL;
}
return addr;
}
+static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ int window;
+ unsigned long long qdr_max;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+ else
+ qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+
+ if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ BUG(); /* MN access can not come here */
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ return 1;
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
+ return 1;
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
+ /* QDR network side */
+ window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f;
+ if (adapter->ahw.qdr_sn_window == window)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags;
+ void *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ unsigned long mem_base;
+ unsigned long mem_page;
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ start = adapter->pci_set_window(adapter, off);
+ if ((start == -1UL) ||
+ (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ printk(KERN_ERR "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", netxen_nic_driver_name, off);
+ return -1;
+ }
+
+ addr = (void *)(pci_base_offset(adapter, start));
+ if (!addr) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ mem_base = pci_resource_start(adapter->pdev, 0);
+ mem_page = start & PAGE_MASK;
+ /* Map two pages whenever user tries to access addresses in two
+ consecutive pages.
+ */
+ if (mem_page != ((start + size - 1) & PAGE_MASK))
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+ else
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+ if (mem_ptr == 0UL) {
+ *(uint8_t *)data = 0;
+ return -1;
+ }
+ addr = mem_ptr;
+ addr += start & (PAGE_SIZE - 1);
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = readb(addr);
+ break;
+ case 2:
+ *(uint16_t *)data = readw(addr);
+ break;
+ case 4:
+ *(uint32_t *)data = readl(addr);
+ break;
+ case 8:
+ *(uint64_t *)data = readq(addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+
+ if (mem_ptr)
+ iounmap(mem_ptr);
+ return ret;
+}
+
+static int
+netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
+ void *data, int size)
+{
+ unsigned long flags;
+ void *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ unsigned long mem_base;
+ unsigned long mem_page;
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+
+ /*
+ * If attempting to access unknown address or straddle hw windows,
+ * do not access.
+ */
+ start = adapter->pci_set_window(adapter, off);
+ if ((start == -1UL) ||
+ (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ printk(KERN_ERR "%s out of bound pci memory access. "
+ "offset is 0x%llx\n", netxen_nic_driver_name, off);
+ return -1;
+ }
+
+ addr = (void *)(pci_base_offset(adapter, start));
+ if (!addr) {
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ mem_base = pci_resource_start(adapter->pdev, 0);
+ mem_page = start & PAGE_MASK;
+ /* Map two pages whenever user tries to access addresses in two
+ * consecutive pages.
+ */
+ if (mem_page != ((start + size - 1) & PAGE_MASK))
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
+ else
+ mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+ if (mem_ptr == 0UL)
+ return -1;
+ addr = mem_ptr;
+ addr += start & (PAGE_SIZE - 1);
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ }
+
+ switch (size) {
+ case 1:
+ writeb(*(uint8_t *)data, addr);
+ break;
+ case 2:
+ writew(*(uint16_t *)data, addr);
+ break;
+ case 4:
+ writel(*(uint32_t *)data, addr);
+ break;
+ case 8:
+ writeq(*(uint64_t *)data, addr);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ DPRINTK(1, INFO, "writing data %llx to offset %llx\n",
+ *(unsigned long long *)data, start);
+ if (mem_ptr)
+ iounmap(mem_ptr);
+ return ret;
+}
+
+#define MAX_CTL_CHECK 1000
+
+int
+netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j, ret = 0, loop, sz[2], off0;
+ uint32_t temp;
+ uint64_t off8, tmpw, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_write_direct(adapter,
+ off, data, size);
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+ mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter,
+ off8 + (i << 3), &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(word[i] & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+ writel((word[i] >> 32) & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+ writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk("%s: %s Fail to write through agent\n",
+ __func__, netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ return ret;
+}
+
+int
+netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ uint32_t temp;
+ uint64_t off8, val, word[2] = {0, 0};
+
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_read_direct(adapter, off, data, size);
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+ mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: %s Fail to read through agent\n",
+ __func__, netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ word[i] |= ((uint64_t) readl(
+ (void *)(mem_crb +
+ MIU_TEST_AGT_RDDATA(k))) << (32*k));
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+int
+netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ int i, j, ret = 0, loop, sz[2], off0;
+ uint32_t temp;
+ uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+ if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+ mem_crb = NETXEN_CRB_QDR_NET;
+ else {
+ mem_crb = NETXEN_CRB_DDR_NET;
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_write_direct(adapter,
+ off, data, size);
+ }
+
+ off8 = off & 0xfffffff8;
+ off0 = off & 0x7;
+ sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+ sz[1] = size - sz[0];
+ loop = ((off0 + size - 1) >> 3) + 1;
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter, off8 + (i << 3),
+ &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = word[i] & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+ temp = (word[i] >> 32) & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to write through agent\n",
+ netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+ return ret;
+}
+
+int
+netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ uint32_t temp;
+ uint64_t off8, val, mem_crb, word[2] = {0, 0};
+
+ /*
+ * If not MN, go check for MS or invalid.
+ */
+
+ if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+ mem_crb = NETXEN_CRB_QDR_NET;
+ else {
+ mem_crb = NETXEN_CRB_DDR_NET;
+ if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+ return netxen_nic_pci_mem_read_direct(adapter,
+ off, data, size);
+ }
+
+ off8 = off & 0xfffffff8;
+ off0[0] = off & 0x7;
+ off0[1] = 0;
+ sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+ sz[1] = size - sz[0];
+ loop = ((off0[0] + size - 1) >> 3) + 1;
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to read through agent\n",
+ netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+ word[i] |= ((uint64_t)temp << (32 * k));
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+}
+
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
#if 0
int
netxen_nic_erase_pxe(struct netxen_adapter *adapter)
@@ -1003,12 +2010,25 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
adapter->ahw.board_type = NETXEN_NIC_XGBE;
break;
case NETXEN_BRDTYPE_P1_BD:
case NETXEN_BRDTYPE_P1_SB:
case NETXEN_BRDTYPE_P1_SMAX:
case NETXEN_BRDTYPE_P1_SOCK:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+
adapter->ahw.board_type = NETXEN_NIC_GBE;
break;
default:
@@ -1042,25 +2062,11 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
return 0;
}
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
-{
- netxen_niu_gbe_init_port(adapter, adapter->physical_port);
-}
-
void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
- int data)
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+ unsigned long off, int data)
{
- void __iomem *addr;
-
- if (ADDR_IN_WINDOW1(off)) {
- writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
+ adapter->hw_write_wx(adapter, off, &data, 4);
}
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
@@ -1147,12 +2153,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
addr += sizeof(u32);
}
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build =
- readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+
+ adapter->fw_major = fw_major;
if (adapter->portnum == 0) {
get_brd_name_by_type(board_info->board_type, brd_name);
@@ -1163,28 +2168,13 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
fw_minor, fw_build);
}
- if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
- adapter->driver_mismatch = 1;
- }
- if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
- fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
+ if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
+ NETXEN_VERSION_CODE(3, 4, 216)) {
adapter->driver_mismatch = 1;
- }
- if (adapter->driver_mismatch) {
- printk(KERN_ERR "%s: driver and firmware version mismatch\n",
- adapter->netdev->name);
+ printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
+ netxen_nic_driver_name,
+ fw_major, fw_minor, fw_build);
return;
}
-
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
- adapter->netdev->name);
- break;
- case NETXEN_NIC_XGBE:
- dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
- adapter->netdev->name);
- break;
- }
}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index a3ea1dd98c4..b8e0030f03d 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -82,19 +82,9 @@ struct netxen_adapter;
#define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20)
-#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \
- addr = pci_base_offset(adapter, X); \
- *(u32 *)Y = readl((void __iomem*) addr);
-
struct netxen_port;
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
void netxen_nic_flash_print(struct netxen_adapter *adapter);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
- unsigned long off, int data);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
typedef u8 netxen_ethernet_macaddr_t[6];
@@ -432,7 +422,8 @@ typedef enum {
/* Promiscous mode options (GbE mode only) */
typedef enum {
NETXEN_NIU_PROMISC_MODE = 0,
- NETXEN_NIU_NON_PROMISC_MODE
+ NETXEN_NIU_NON_PROMISC_MODE,
+ NETXEN_NIU_ALLMULTI_MODE
} netxen_niu_prom_mode_t;
/*
@@ -478,42 +469,6 @@ typedef enum {
#define netxen_xg_soft_reset(config_word) \
((config_word) |= 1 << 4)
-/*
- * MAC Control Register
- *
- * Bit 0-1 : id_pool0
- * Bit 2 : enable_xtnd0
- * Bit 4-5 : id_pool1
- * Bit 6 : enable_xtnd1
- * Bit 8-9 : id_pool2
- * Bit 10 : enable_xtnd2
- * Bit 12-13 : id_pool3
- * Bit 14 : enable_xtnd3
- * Bit 24-25 : mode_select
- * Bit 28-31 : enable_pool
- */
-
-#define netxen_nic_mcr_set_id_pool0(config, val) \
- ((config) |= ((val) &0x03))
-#define netxen_nic_mcr_set_enable_xtnd0(config) \
- ((config) |= 1 << 3)
-#define netxen_nic_mcr_set_id_pool1(config, val) \
- ((config) |= (((val) & 0x03) << 4))
-#define netxen_nic_mcr_set_enable_xtnd1(config) \
- ((config) |= 1 << 6)
-#define netxen_nic_mcr_set_id_pool2(config, val) \
- ((config) |= (((val) & 0x03) << 8))
-#define netxen_nic_mcr_set_enable_xtnd2(config) \
- ((config) |= 1 << 10)
-#define netxen_nic_mcr_set_id_pool3(config, val) \
- ((config) |= (((val) & 0x03) << 12))
-#define netxen_nic_mcr_set_enable_xtnd3(config) \
- ((config) |= 1 << 14)
-#define netxen_nic_mcr_set_mode_select(config, val) \
- ((config) |= (((val) & 0x03) << 24))
-#define netxen_nic_mcr_set_enable_pool(config, val) \
- ((config) |= (((val) & 0x0f) << 28))
-
/* Set promiscuous mode for a GbE interface */
int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
netxen_niu_prom_mode_t mode);
@@ -538,4 +493,15 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter);
int netxen_niu_disable_xg_port(struct netxen_adapter *adapter);
+typedef struct {
+ unsigned valid;
+ unsigned start_128M;
+ unsigned end_128M;
+ unsigned start_2M;
+} crb_128M_2M_sub_block_map_t;
+
+typedef struct {
+ crb_128M_2M_sub_block_map_t sub_block[16];
+} crb_128M_2M_block_map_t;
+
#endif /* __NETXEN_NIC_HW_H_ */
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 70d1b22ced2..01ab31b34a8 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -42,8 +42,6 @@ struct crb_addr_pair {
u32 data;
};
-unsigned long last_schedule_time;
-
#define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
#define NETXEN_ADDR_ERROR (0xffffffff)
@@ -117,6 +115,8 @@ static void crb_addr_transform_setup(void)
crb_addr_transform(C2C1);
crb_addr_transform(C2C0);
crb_addr_transform(SMB);
+ crb_addr_transform(OCM0);
+ crb_addr_transform(I2C0);
}
int netxen_init_firmware(struct netxen_adapter *adapter)
@@ -124,15 +124,15 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
u32 state = 0, loops = 0, err = 0;
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
if (state == PHAN_INITIALIZE_ACK)
return 0;
while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
- udelay(100);
+ msleep(1);
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
loops++;
}
@@ -143,64 +143,193 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
return err;
}
/* Window 1 call */
- writel(INTR_SCHEME_PERPORT,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
- writel(MSI_MODE_MULTIFUNC,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
- writel(MPORT_MULTI_FUNCTION_MODE,
- NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
- writel(PHAN_INITIALIZE_ACK,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+ adapter->pci_write_normalize(adapter,
+ CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
return err;
}
-#define NETXEN_ADDR_LIMIT 0xffffffffULL
+void netxen_release_rx_buffers(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int i, ctxid, ring;
+
+ for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+ recv_ctx = &adapter->recv_ctx[ctxid];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ for (i = 0; i < rds_ring->max_rx_desc_count; ++i) {
+ rx_buf = &(rds_ring->rx_buf_arr[i]);
+ if (rx_buf->state == NETXEN_BUFFER_FREE)
+ continue;
+ pci_unmap_single(adapter->pdev,
+ rx_buf->dma,
+ rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+ if (rx_buf->skb != NULL)
+ dev_kfree_skb_any(rx_buf->skb);
+ }
+ }
+ }
+}
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev)
+void netxen_release_tx_buffers(struct netxen_adapter *adapter)
{
- void *addr;
+ struct netxen_cmd_buffer *cmd_buf;
+ struct netxen_skb_frag *buffrag;
+ int i, j;
+
+ cmd_buf = adapter->cmd_buf_arr;
+ for (i = 0; i < adapter->max_tx_desc_count; i++) {
+ buffrag = cmd_buf->frag_array;
+ if (buffrag->dma) {
+ pci_unmap_single(adapter->pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ for (j = 0; j < cmd_buf->frag_count; j++) {
+ buffrag++;
+ if (buffrag->dma) {
+ pci_unmap_page(adapter->pdev, buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ }
+ /* Free the skb we received in netxen_nic_xmit_frame */
+ if (cmd_buf->skb) {
+ dev_kfree_skb_any(cmd_buf->skb);
+ cmd_buf->skb = NULL;
+ }
+ cmd_buf++;
+ }
+}
- addr = pci_alloc_consistent(pdev, sz, ptr);
- if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
- *used_dev = pdev;
- return addr;
+void netxen_free_sw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ if (rds_ring->rx_buf_arr) {
+ vfree(rds_ring->rx_buf_arr);
+ rds_ring->rx_buf_arr = NULL;
+ }
+ }
}
- pci_free_consistent(pdev, sz, addr, *ptr);
- addr = pci_alloc_consistent(NULL, sz, ptr);
- *used_dev = NULL;
- return addr;
+ if (adapter->cmd_buf_arr)
+ vfree(adapter->cmd_buf_arr);
+ return;
}
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
{
- int ctxid, ring;
- u32 i;
- u32 num_rx_bufs = 0;
- struct netxen_rcv_desc_ctx *rcv_desc;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int ctx, ring, i, num_rx_bufs;
- DPRINTK(INFO, "initializing some queues: %p\n", adapter);
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- struct netxen_rx_buffer *rx_buf;
- rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
- rcv_desc->begin_alloc = 0;
- rx_buf = rcv_desc->rx_buf_arr;
- num_rx_bufs = rcv_desc->max_rx_desc_count;
+ struct netxen_cmd_buffer *cmd_buf_arr;
+ struct net_device *netdev = adapter->netdev;
+
+ cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+ if (cmd_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+ netdev->name);
+ return -ENOMEM;
+ }
+ memset(cmd_buf_arr, 0, TX_RINGSIZE);
+ adapter->cmd_buf_arr = cmd_buf_arr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ switch (RCV_DESC_TYPE(ring)) {
+ case RCV_DESC_NORMAL:
+ rds_ring->max_rx_desc_count =
+ adapter->max_rx_desc_count;
+ rds_ring->flags = RCV_DESC_NORMAL;
+ if (adapter->ahw.cut_through) {
+ rds_ring->dma_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ rds_ring->skb_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ } else {
+ rds_ring->dma_size = RX_DMA_MAP_LEN;
+ rds_ring->skb_size =
+ MAX_RX_BUFFER_LENGTH;
+ }
+ break;
+
+ case RCV_DESC_JUMBO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_jumbo_rx_desc_count;
+ rds_ring->flags = RCV_DESC_JUMBO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ rds_ring->dma_size =
+ NX_P3_RX_JUMBO_BUF_MAX_LEN;
+ else
+ rds_ring->dma_size =
+ NX_P2_RX_JUMBO_BUF_MAX_LEN;
+ rds_ring->skb_size =
+ rds_ring->dma_size + NET_IP_ALIGN;
+ break;
+
+ case RCV_RING_LRO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_lro_rx_desc_count;
+ rds_ring->flags = RCV_DESC_LRO;
+ rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+ rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+ break;
+
+ }
+ rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+ vmalloc(RCV_BUFFSIZE);
+ if (rds_ring->rx_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate "
+ "rx buffer ring %d\n",
+ netdev->name, ring);
+ /* free whatever was already allocated */
+ goto err_out;
+ }
+ memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
+ INIT_LIST_HEAD(&rds_ring->free_list);
+ rds_ring->begin_alloc = 0;
/*
* Now go through all of them, set reference handles
* and put them in the queues.
*/
+ num_rx_bufs = rds_ring->max_rx_desc_count;
+ rx_buf = rds_ring->rx_buf_arr;
for (i = 0; i < num_rx_bufs; i++) {
+ list_add_tail(&rx_buf->list,
+ &rds_ring->free_list);
rx_buf->ref_handle = i;
rx_buf->state = NETXEN_BUFFER_FREE;
- DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
- "%p\n", ctxid, i, rx_buf);
rx_buf++;
}
}
}
+
+ return 0;
+
+err_out:
+ netxen_free_sw_resources(adapter);
+ return -ENOMEM;
}
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
@@ -211,14 +340,12 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_gbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_gbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_gb;
adapter->set_promisc = netxen_niu_set_promiscuous_mode;
- adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
adapter->phy_read = netxen_niu_gbe_phy_read;
adapter->phy_write = netxen_niu_gbe_phy_write;
- adapter->init_niu = netxen_nic_init_niu_gb;
+ adapter->init_port = netxen_niu_gbe_init_port;
adapter->stop_port = netxen_niu_disable_gbe_port;
break;
@@ -227,12 +354,10 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_xgbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_xgbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_xg_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_xgb;
adapter->init_port = netxen_niu_xg_init_port;
adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
- adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
adapter->stop_port = netxen_niu_disable_xg_port;
break;
@@ -270,7 +395,9 @@ static u32 netxen_decode_crb_addr(u32 addr)
static long rom_max_timeout = 100;
static long rom_lock_timeout = 10000;
+#if 0
static long rom_write_timeout = 700;
+#endif
static int rom_lock(struct netxen_adapter *adapter)
{
@@ -319,6 +446,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
return 0;
}
+#if 0
static int netxen_rom_wren(struct netxen_adapter *adapter)
{
/* Set write enable latch in ROM status register */
@@ -348,6 +476,7 @@ static int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
}
return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
}
+#endif
static void netxen_rom_unlock(struct netxen_adapter *adapter)
{
@@ -358,6 +487,7 @@ static void netxen_rom_unlock(struct netxen_adapter *adapter)
}
+#if 0
static int netxen_rom_wip_poll(struct netxen_adapter *adapter)
{
long timeout = 0;
@@ -393,6 +523,7 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
return netxen_rom_wip_poll(adapter);
}
+#endif
static int do_rom_fast_read(struct netxen_adapter *adapter,
int addr, int *valp)
@@ -475,7 +606,6 @@ int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
netxen_rom_unlock(adapter);
return ret;
}
-#endif /* 0 */
static int do_rom_fast_write_words(struct netxen_adapter *adapter,
int addr, u8 *bytes, size_t size)
@@ -740,28 +870,25 @@ int netxen_flash_unlock(struct netxen_adapter *adapter)
return ret;
}
+#endif /* 0 */
#define NETXEN_BOARDTYPE 0x4008
#define NETXEN_BOARDNUM 0x400c
#define NETXEN_CHIPNUM 0x4010
-#define NETXEN_ROMBUS_RESET 0xFFFFFFFF
-#define NETXEN_ROM_FIRST_BARRIER 0x800000000ULL
-#define NETXEN_ROM_FOUND_INIT 0x400
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
int addr, val;
- int n, i;
- int init_delay = 0;
+ int i, init_delay = 0;
struct crb_addr_pair *buf;
+ unsigned offset, n;
u32 off;
/* resetall */
netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- NETXEN_ROMBUS_RESET);
+ 0xffffffff);
if (verbose) {
- int val;
if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
printk("P2 ROM board type: 0x%08x\n", val);
else
@@ -776,117 +903,141 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
printk("Could not read chip number\n");
}
- if (netxen_rom_fast_read(adapter, 0, &n) == 0
- && (n & NETXEN_ROM_FIRST_BARRIER)) {
- n &= ~NETXEN_ROM_ROUNDUP;
- if (n < NETXEN_ROM_FOUND_INIT) {
- if (verbose)
- printk("%s: %d CRB init values found"
- " in ROM.\n", netxen_nic_driver_name, n);
- } else {
- printk("%s:n=0x%x Error! NetXen card flash not"
- " initialized.\n", __FUNCTION__, n);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ (n != 0xcafecafeUL) ||
+ netxen_rom_fast_read(adapter, 4, &n) != 0) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
return -EIO;
}
- buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
- if (buf == NULL) {
- printk("%s: netxen_pinit_from_rom: Unable to calloc "
- "memory.\n", netxen_nic_driver_name);
- return -ENOMEM;
- }
- for (i = 0; i < n; i++) {
- if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
- || netxen_rom_fast_read(adapter, 8 * i + 8,
- &addr) != 0)
- return -EIO;
-
- buf[i].addr = addr;
- buf[i].data = val;
-
- if (verbose)
- printk("%s: PCI: 0x%08x == 0x%08x\n",
- netxen_nic_driver_name, (unsigned int)
- netxen_decode_crb_addr(addr), val);
+ offset = n & 0xffffU;
+ n = (n >> 16) & 0xffffU;
+ } else {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ !(n & 0x80000000)) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
+ return -EIO;
}
- for (i = 0; i < n; i++) {
+ offset = 1;
+ n &= ~0x80000000;
+ }
+
+ if (n < 1024) {
+ if (verbose)
+ printk(KERN_DEBUG "%s: %d CRB init values found"
+ " in ROM.\n", netxen_nic_driver_name, n);
+ } else {
+ printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
+ " initialized.\n", __func__, n);
+ return -EIO;
+ }
+
+ buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+ if (buf == NULL) {
+ printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+ for (i = 0; i < n; i++) {
+ if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+ netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0)
+ return -EIO;
+
+ buf[i].addr = addr;
+ buf[i].data = val;
- off = netxen_decode_crb_addr(buf[i].addr);
- if (off == NETXEN_ADDR_ERROR) {
- printk(KERN_ERR"CRB init value out of range %x\n",
+ if (verbose)
+ printk(KERN_DEBUG "%s: PCI: 0x%08x == 0x%08x\n",
+ netxen_nic_driver_name,
+ (u32)netxen_decode_crb_addr(addr), val);
+ }
+ for (i = 0; i < n; i++) {
+
+ off = netxen_decode_crb_addr(buf[i].addr);
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR"CRB init value out of range %x\n",
buf[i].addr);
+ continue;
+ }
+ off += NETXEN_PCI_CRBSPACE;
+ /* skipping cold reboot MAGIC */
+ if (off == NETXEN_CAM_RAM(0x1fc))
+ continue;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ /* do not reset PCI */
+ if (off == (ROMUSB_GLB + 0xbc))
continue;
- }
- off += NETXEN_PCI_CRBSPACE;
- /* skipping cold reboot MAGIC */
- if (off == NETXEN_CAM_RAM(0x1fc))
+ if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
+ buf[i].data = 0x1020;
+ /* skip the function enable register */
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
+ continue;
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
continue;
+ if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
+ continue;
+ }
- /* After writing this register, HW needs time for CRB */
- /* to quiet down (else crb_window returns 0xffffffff) */
- if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
- init_delay = 1;
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
+ netxen_nic_driver_name, buf[i].addr);
+ continue;
+ }
+
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+ init_delay = 1;
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* hold xdma in reset also */
buf[i].data = NETXEN_NIC_XDMA_RESET;
}
+ }
- if (ADDR_IN_WINDOW1(off)) {
- writel(buf[i].data,
- NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- writel(buf[i].data,
- pci_base_offset(adapter, off));
+ adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
- if (init_delay == 1) {
- msleep(1000);
- init_delay = 0;
- }
- msleep(1);
+ if (init_delay == 1) {
+ msleep(1000);
+ init_delay = 0;
}
- kfree(buf);
+ msleep(1);
+ }
+ kfree(buf);
- /* disable_peg_cache_all */
+ /* disable_peg_cache_all */
- /* unreset_net_cache */
- netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
- 4);
- netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- (val & 0xffffff0f));
- /* p2dn replyCount */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
- /* disable_peg_cache 0 */
+ /* unreset_net_cache */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0x4c, 8);
- /* disable_peg_cache 1 */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_I + 0x4c, 8);
-
- /* peg_clr_all */
-
- /* peg_clr 0 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
- 0);
- /* peg_clr 1 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
- 0);
- /* peg_clr 2 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
- 0);
- /* peg_clr 3 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
- 0);
+ NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
}
+
+ /* p2dn replyCount */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+ /* disable_peg_cache 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+ /* disable_peg_cache 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+ /* peg_clr_all */
+
+ /* peg_clr 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+ /* peg_clr 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+ /* peg_clr 2 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+ /* peg_clr 3 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
return 0;
}
@@ -897,12 +1048,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
uint32_t lo;
adapter->dummy_dma.addr =
- pci_alloc_consistent(adapter->ahw.pdev,
+ pci_alloc_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
&adapter->dummy_dma.phys_addr);
if (adapter->dummy_dma.addr == NULL) {
printk("%s: ERROR: Could not allocate dummy DMA memory\n",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
@@ -910,8 +1061,13 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
hi = (addr >> 32) & 0xffffffff;
lo = addr & 0xffffffff;
- writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
- writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ uint32_t temp = 0;
+ adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+ }
return 0;
}
@@ -931,7 +1087,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
} while (--i);
if (i) {
- pci_free_consistent(adapter->ahw.pdev,
+ pci_free_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
adapter->dummy_dma.addr,
adapter->dummy_dma.phys_addr);
@@ -946,22 +1102,24 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
{
u32 val = 0;
- int retries = 30;
+ int retries = 60;
if (!pegtune_val) {
do {
- val = readl(NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMDPEG_STATE));
- pegtune_val = readl(NETXEN_CRB_NORMALIZE
- (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+ val = adapter->pci_read_normalize(adapter,
+ CRB_CMDPEG_STATE);
if (val == PHAN_INITIALIZE_COMPLETE ||
val == PHAN_INITIALIZE_ACK)
return 0;
- msleep(1000);
+ msleep(500);
+
} while (--retries);
+
if (!retries) {
+ pegtune_val = adapter->pci_read_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
printk(KERN_WARNING "netxen_phantom_init: init failed, "
"pegtune_val=%x\n", pegtune_val);
return -1;
@@ -971,58 +1129,61 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
return 0;
}
-static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+int netxen_receive_peg_ready(struct netxen_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- uint32_t temp, temp_state, temp_val;
- int rv = 0;
-
- temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
-
- temp_state = nx_get_temp_state(temp);
- temp_val = nx_get_temp_val(temp);
-
- if (temp_state == NX_TEMP_PANIC) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C exceeds"
- " maximum allowed. Hardware has been shut down.\n",
- netxen_nic_driver_name, temp_val);
-
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- rv = 1;
- } else if (temp_state == NX_TEMP_WARN) {
- if (adapter->temp == NX_TEMP_NORMAL) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C "
- "exceeds operating range."
- " Immediate action needed.\n",
- netxen_nic_driver_name, temp_val);
- }
- } else {
- if (adapter->temp == NX_TEMP_WARN) {
- printk(KERN_INFO
- "%s: Device temperature is now %d degrees C"
- " in normal range.\n", netxen_nic_driver_name,
- temp_val);
- }
+ u32 val = 0;
+ int retries = 2000;
+
+ do {
+ val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(10);
+
+ } while (--retries);
+
+ if (!retries) {
+ printk(KERN_ERR "Receive Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
}
- adapter->temp = temp_state;
- return rv;
+
+ return 0;
}
-void netxen_watchdog_task(struct work_struct *work)
+static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
+ struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
{
- struct netxen_adapter *adapter =
- container_of(work, struct netxen_adapter, watchdog_task);
+ struct netxen_rx_buffer *buffer;
+ struct sk_buff *skb;
- if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
- return;
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
- if (adapter->handle_phy_intr)
- adapter->handle_phy_intr(adapter);
+ skb = buffer->skb;
+ if (!skb)
+ goto no_skb;
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+ if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+ adapter->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb->dev = adapter->netdev;
+
+ buffer->skb = NULL;
+
+no_skb:
+ buffer->state = NETXEN_BUFFER_FREE;
+ buffer->lro_current_frags = 0;
+ buffer->lro_expected_frags = 0;
+ list_add_tail(&buffer->list, &rds_ring->free_list);
+ return skb;
}
/*
@@ -1031,9 +1192,8 @@ void netxen_watchdog_task(struct work_struct *work)
* invoke the routine to send more rx buffers to the Phantom...
*/
static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
- struct status_desc *desc)
+ struct status_desc *desc, struct status_desc *frag_desc)
{
- struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
u64 sts_data = le64_to_cpu(desc->status_desc_data);
int index = netxen_get_sts_refhandle(sts_data);
@@ -1042,8 +1202,8 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
struct sk_buff *skb;
u32 length = netxen_get_sts_totallength(sts_data);
u32 desc_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ret;
+ u16 pkt_offset = 0, cksum;
+ struct nx_host_rds_ring *rds_ring;
desc_ctx = netxen_get_sts_type(sts_data);
if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
@@ -1052,13 +1212,13 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
return;
}
- rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
- if (unlikely(index > rcv_desc->max_rx_desc_count)) {
+ rds_ring = &recv_ctx->rds_rings[desc_ctx];
+ if (unlikely(index > rds_ring->max_rx_desc_count)) {
DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
- index, rcv_desc->max_rx_desc_count);
+ index, rds_ring->max_rx_desc_count);
return;
}
- buffer = &rcv_desc->rx_buf_arr[index];
+ buffer = &rds_ring->rx_buf_arr[index];
if (desc_ctx == RCV_DESC_LRO_CTXID) {
buffer->lro_current_frags++;
if (netxen_get_sts_desc_lro_last_frag(desc)) {
@@ -1079,43 +1239,52 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
}
}
- pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
+ cksum = netxen_get_sts_status(sts_data);
- skb = (struct sk_buff *)buffer->skb;
-
- if (likely(adapter->rx_csum &&
- netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
- adapter->stats.csummed++;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else
- skb->ip_summed = CHECKSUM_NONE;
+ skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
- skb->dev = netdev;
if (desc_ctx == RCV_DESC_LRO_CTXID) {
/* True length was only available on the last pkt */
skb_put(skb, buffer->lro_length);
} else {
- skb_put(skb, length);
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
}
skb->protocol = eth_type_trans(skb, netdev);
- ret = netif_receive_skb(skb);
- netdev->last_rx = jiffies;
-
- rcv_desc->rcv_pending--;
-
/*
- * We just consumed one buffer so post a buffer.
+ * rx buffer chaining is disabled, walk and free
+ * any spurious rx buffer chain.
*/
- buffer->skb = NULL;
- buffer->state = NETXEN_BUFFER_FREE;
- buffer->lro_current_frags = 0;
- buffer->lro_expected_frags = 0;
+ if (frag_desc) {
+ u16 i, nr_frags = desc->nr_frags;
+
+ dev_kfree_skb_any(skb);
+ for (i = 0; i < nr_frags; i++) {
+ index = frag_desc->frag_handles[i];
+ skb = netxen_process_rxbuf(adapter,
+ rds_ring, index, cksum);
+ if (skb)
+ dev_kfree_skb_any(skb);
+ }
+ adapter->stats.rxdropped++;
+ } else {
- adapter->stats.no_rcv++;
- adapter->stats.rxbytes += length;
+ netif_receive_skb(skb);
+ netdev->last_rx = jiffies;
+
+ adapter->stats.no_rcv++;
+ adapter->stats.rxbytes += length;
+ }
}
/* Process Receive status ring */
@@ -1123,10 +1292,11 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
{
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
- struct status_desc *desc; /* used to read status desc here */
+ struct status_desc *desc, *frag_desc;
u32 consumer = recv_ctx->status_rx_consumer;
- u32 producer = 0;
int count = 0, ring;
+ u64 sts_data;
+ u16 opcode;
while (count < max) {
desc = &desc_head[consumer];
@@ -1135,24 +1305,38 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
netxen_get_sts_owner(desc));
break;
}
- netxen_process_rcv(adapter, ctxid, desc);
+
+ sts_data = le64_to_cpu(desc->status_desc_data);
+ opcode = netxen_get_sts_opcode(sts_data);
+ frag_desc = NULL;
+ if (opcode == NETXEN_NIC_RXPKT_DESC) {
+ if (desc->nr_frags) {
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
+ frag_desc = &desc_head[consumer];
+ netxen_set_sts_owner(frag_desc,
+ STATUS_OWNER_PHANTOM);
+ }
+ }
+
+ netxen_process_rcv(adapter, ctxid, desc, frag_desc);
+
netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
- consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
count++;
}
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
/* update the consumer index in phantom */
if (count) {
recv_ctx->status_rx_consumer = consumer;
- recv_ctx->status_rx_producer = producer;
/* Window = 1 */
- writel(consumer,
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[adapter->portnum].
- crb_rcv_status_consumer));
+ adapter->pci_write_normalize(adapter,
+ recv_ctx->crb_sts_consumer, consumer);
}
return count;
@@ -1231,10 +1415,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
*/
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
uint producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
@@ -1242,41 +1426,36 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
int index = 0;
netxen_ctx_msg msg = 0;
dma_addr_t dma;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
+
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * TODO
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
+ pdesc = &rds_ring->desc_head[producer];
-#if defined(XGB_DEBUG)
- *(unsigned long *)(skb->head) = 0xc0debabe;
- if (skb_is_nonlinear(skb)) {
- printk("Allocated SKB @%p is nonlinear\n");
- }
-#endif
- skb_reserve(skb, 2);
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
/* This will be setup when we receive the
* buffer after it has been filled FSL TBD TBD
* skb->dev = netdev;
*/
- dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
+ dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
@@ -1284,112 +1463,101 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
buffer->dma = dma;
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
+
+ if (adapter->fw_major < 4) {
/*
* Write a doorbell msg to tell phanmon of change in
* receive ring producer
+ * Only for firmware version < 4.0.0
*/
netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
netxen_set_msg_privid(msg);
netxen_set_msg_count(msg,
((producer -
- 1) & (rcv_desc->
+ 1) & (rds_ring->
max_rx_desc_count - 1)));
netxen_set_msg_ctxid(msg, adapter->portnum);
netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
writel(msg,
DB_NORMALIZE(adapter,
NETXEN_RCV_PRODUCER_OFFSET));
+ }
}
}
static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
uint32_t ctx, uint32_t ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
u32 producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
int index = 0;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
- skb_reserve(skb, 2);
- /*
- * This will be setup when we receive the
- * buffer after it has been filled
- * skb->dev = netdev;
- */
+ pdesc = &rds_ring->desc_head[producer];
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = pci_map_single(pdev, skb->data,
- rcv_desc->dma_size,
+ rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
+ buffer = &rds_ring->rx_buf_arr[index];
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
wmb();
}
}
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
deleted file mode 100644
index 96cec41f901..00000000000
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.
- *
- * Contact Information:
- * info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- */
-
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include "netxen_nic.h"
-#include "netxen_nic_hw.h"
-#include "netxen_nic_phan_reg.h"
-
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
-{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *stats = &adapter->net_stats;
-
- memset(stats, 0, sizeof(*stats));
-
- /* total packets received */
- stats->rx_packets = adapter->stats.no_rcv;
- /* total packets transmitted */
- stats->tx_packets = adapter->stats.xmitedframes +
- adapter->stats.xmitfinished;
- /* total bytes received */
- stats->rx_bytes = adapter->stats.rxbytes;
- /* total bytes transmitted */
- stats->tx_bytes = adapter->stats.txbytes;
- /* bad packets received */
- stats->rx_errors = adapter->stats.rcvdbadskb;
- /* packet transmit problems */
- stats->tx_errors = adapter->stats.nocmddescriptor;
- /* no space in linux buffers */
- stats->rx_dropped = adapter->stats.rxdropped;
- /* no space available in linux */
- stats->tx_dropped = adapter->stats.txdropped;
-
- return stats;
-}
-
-static void netxen_indicate_link_status(struct netxen_adapter *adapter,
- u32 link)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (link)
- netif_carrier_on(netdev);
- else
- netif_carrier_off(netdev);
-}
-
-#if 0
-void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable)
-{
- __u32 int_src;
-
- /* This should clear the interrupt source */
- if (adapter->phy_read)
- adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
- &int_src);
- if (int_src == 0) {
- DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
- return;
- }
- if (adapter->disable_phy_interrupts)
- adapter->disable_phy_interrupts(adapter);
-
- if (netxen_get_phy_int_jabber(int_src))
- DPRINTK(INFO, "Jabber interrupt \n");
-
- if (netxen_get_phy_int_polarity_changed(int_src))
- DPRINTK(INFO, "POLARITY CHANGED int \n");
-
- if (netxen_get_phy_int_energy_detect(int_src))
- DPRINTK(INFO, "ENERGY DETECT INT \n");
-
- if (netxen_get_phy_int_downshift(int_src))
- DPRINTK(INFO, "DOWNSHIFT INT \n");
- /* write it down later.. */
- if ((netxen_get_phy_int_speed_changed(int_src))
- || (netxen_get_phy_int_link_status_changed(int_src))) {
- __u32 status;
-
- DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
-
- if (adapter->phy_read
- && adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- &status) == 0) {
- if (netxen_get_phy_int_link_status_changed(int_src)) {
- if (netxen_get_phy_link(status)) {
- printk(KERN_INFO "%s: %s Link UP\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
-
- } else {
- printk(KERN_INFO "%s: %s Link DOWN\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
- }
- netxen_indicate_link_status(adapter,
- netxen_get_phy_link
- (status));
- }
- }
- }
- if (adapter->enable_phy_interrupts)
- adapter->enable_phy_interrupts(adapter);
-}
-#endif /* 0 */
-
-static void netxen_nic_isr_other(struct netxen_adapter *adapter)
-{
- int portno = adapter->portnum;
- u32 val, linkup, qg_linksup;
-
- /* verify the offset */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val = val >> adapter->physical_port;
- if (val == adapter->ahw.qg_linksup)
- return;
-
- qg_linksup = adapter->ahw.qg_linksup;
- adapter->ahw.qg_linksup = val;
- DPRINTK(INFO, "link update 0x%08x\n", val);
-
- linkup = val & 1;
-
- if (linkup != (qg_linksup & 1)) {
- printk(KERN_INFO "%s: %s PORT %d link %s\n",
- adapter->netdev->name,
- netxen_nic_driver_name, portno,
- ((linkup == 0) ? "down" : "up"));
- netxen_indicate_link_status(adapter, linkup);
- if (linkup)
- netxen_nic_set_link_parameters(adapter);
-
- }
-}
-
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- netxen_nic_isr_other(adapter);
-}
-
-#if 0
-int netxen_nic_link_ok(struct netxen_adapter *adapter)
-{
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- return ((adapter->ahw.qg_linksup) & 1);
-
- case NETXEN_NIC_XGBE:
- return ((adapter->ahw.xg_linkup) & 1);
-
- default:
- printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
- netxen_nic_driver_name, __FUNCTION__);
- break;
- }
-
- return 0;
-}
-#endif /* 0 */
-
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- u32 val;
-
- /* WINDOW = 1 */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val >>= (adapter->physical_port * 8);
- val &= 0xff;
-
- if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is down\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 0;
- if (netif_running(netdev)) {
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is up\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 1;
- netif_carrier_on(netdev);
- netif_wake_queue(netdev);
- }
-}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 63cd67b931e..91d209a8f6c 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -49,13 +49,18 @@ char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
-#define NETXEN_NETDEV_WEIGHT 120
-#define NETXEN_ADAPTER_UP_MAGIC 777
-#define NETXEN_NIC_PEG_TUNE 0
+static int port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+
+/* Default to restricted 1G auto-neg mode */
+static int wol_port_mode = 5;
+
+static int use_msi = 1;
+
+static int use_msi_x = 1;
/* Local functions to NetXen NIC driver */
static int __devinit netxen_nic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
+ const struct pci_device_id *ent);
static void __devexit netxen_nic_remove(struct pci_dev *pdev);
static int netxen_nic_open(struct net_device *netdev);
static int netxen_nic_close(struct net_device *netdev);
@@ -83,6 +88,7 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
ENTRY(0x0005),
ENTRY(0x0024),
ENTRY(0x0025),
+ ENTRY(0x0100),
{0,}
};
@@ -108,95 +114,61 @@ static struct workqueue_struct *netxen_workq;
static void netxen_watchdog(unsigned long);
-static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
- uint32_t crb_producer)
+static uint32_t crb_cmd_producer[4] = {
+ CRB_CMD_PRODUCER_OFFSET, CRB_CMD_PRODUCER_OFFSET_1,
+ CRB_CMD_PRODUCER_OFFSET_2, CRB_CMD_PRODUCER_OFFSET_3
+};
+
+void
+netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET));
- return;
- case 1:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_1));
- return;
- case 2:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_2));
- return;
- case 3:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_producer, crb_producer);
}
-static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
- u32 crb_consumer)
+static uint32_t crb_cmd_consumer[4] = {
+ CRB_CMD_CONSUMER_OFFSET, CRB_CMD_CONSUMER_OFFSET_1,
+ CRB_CMD_CONSUMER_OFFSET_2, CRB_CMD_CONSUMER_OFFSET_3
+};
+
+static inline void
+netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
+ u32 crb_consumer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET));
- return;
- case 1:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_1));
- return;
- case 2:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_2));
- return;
- case 3:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_consumer, crb_consumer);
}
-#define ADAPTER_LIST_SIZE 12
-
-static uint32_t msi_tgt_status[4] = {
+static uint32_t msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
- ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};
-static uint32_t sw_int_mask[4] = {
- CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
- CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
+static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
static void netxen_nic_disable_int(struct netxen_adapter *adapter)
{
u32 mask = 0x7ff;
int retries = 32;
- int port = adapter->portnum;
int pci_fn = adapter->ahw.pci_func;
if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_intr_mask, 0);
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT)
- writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
do {
- writel(0xffffffff,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
- mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_STATUS, 0xffffffff);
+ mask = adapter->pci_read_immediate(adapter,
+ ISR_INT_VECTOR);
if (!(mask & 0x80))
break;
udelay(10);
@@ -208,8 +180,8 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
}
} else {
if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
- writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
- msi_tgt_status[pci_fn]));
+ adapter->pci_write_immediate(adapter,
+ msi_tgt_status[pci_fn], 0xffffffff);
}
}
}
@@ -217,7 +189,6 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
static void netxen_nic_enable_int(struct netxen_adapter *adapter)
{
u32 mask;
- int port = adapter->portnum;
DPRINTK(1, INFO, "Entered ISR Enable \n");
@@ -235,24 +206,299 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
break;
}
- writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
}
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
mask = 0xbff;
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter,
+ CRB_INT_VECTOR, 0);
}
- writel(mask,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_MASK, mask);
}
DPRINTK(1, INFO, "Done with enable Int\n");
}
+static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int err;
+ uint64_t mask;
+
+#ifdef CONFIG_IA64
+ adapter->dma_mask = DMA_32BIT_MASK;
+#else
+ if (revision_id >= NX_P3_B0) {
+ /* should go to DMA_64BIT_MASK */
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P3_A2) {
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P2_C1) {
+ adapter->dma_mask = DMA_35BIT_MASK;
+ mask = DMA_35BIT_MASK;
+ } else {
+ adapter->dma_mask = DMA_32BIT_MASK;
+ mask = DMA_32BIT_MASK;
+ goto set_32_bit_mask;
+ }
+
+ /*
+ * Consistent DMA mask is set to 32 bit because it cannot be set to
+ * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
+ * come off this pool.
+ */
+ if (pci_set_dma_mask(pdev, mask) == 0 &&
+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) {
+ adapter->pci_using_dac = 1;
+ return 0;
+ }
+#endif /* CONFIG_IA64 */
+
+set_32_bit_mask:
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ DPRINTK(ERR, "No usable DMA configuration, aborting:%d\n", err);
+ return err;
+ }
+
+ adapter->pci_using_dac = 0;
+ return 0;
+}
+
+static void netxen_check_options(struct netxen_adapter *adapter)
+{
+ switch (adapter->ahw.boardcfg.board_type) {
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+ adapter->msix_supported = !!use_msi_x;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P2_SB35_4G:
+ case NETXEN_BRDTYPE_P2_SB31_2G:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+ break;
+
+ default:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+
+ printk(KERN_WARNING "Unknown board type(0x%x)\n",
+ adapter->ahw.boardcfg.board_type);
+ break;
+ }
+
+ adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
+ adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+ adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
+
+ adapter->max_possible_rss_rings = 1;
+ return;
+}
+
+static int
+netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
+{
+ int ret = 0;
+
+ if (first_boot == 0x55555555) {
+ /* This is the first boot after power up */
+
+ /* PCI bus master workaround */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ if (!(first_boot & 0x4)) {
+ first_boot |= 0x4;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ }
+
+ /* This is the first boot after power up */
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+ if (first_boot != 0x80000f) {
+ /* clear the register for future unloads/loads */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), 0);
+ ret = -1;
+ }
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ /* Start P2 boot loader */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+ }
+ return ret;
+}
+
+static void netxen_set_port_mode(struct netxen_adapter *adapter)
+{
+ u32 val, data;
+
+ val = adapter->ahw.boardcfg.board_type;
+ if ((val == NETXEN_BRDTYPE_P3_HMEZ) ||
+ (val == NETXEN_BRDTYPE_P3_XG_LOM)) {
+ if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
+ data = NETXEN_PORT_MODE_802_3_AP;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_XG) {
+ data = NETXEN_PORT_MODE_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_1G;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else {
+ data = NETXEN_PORT_MODE_AUTO_NEG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ }
+
+ if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
+ (wol_port_mode != NETXEN_PORT_MODE_XG) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_1G) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
+ wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+ }
+ adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
+ &wol_port_mode, 4);
+ }
+}
+
+#define PCI_CAP_ID_GEN 0x10
+
+static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
+{
+ u32 pdevfuncsave;
+ u32 c8c9value = 0;
+ u32 chicken = 0;
+ u32 control = 0;
+ int i, pos;
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(0x1166, 0x0140, NULL);
+ if (pdev) {
+ pci_dev_put(pdev);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ chicken |= 0x4000;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ }
+
+ pdev = adapter->pdev;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+ /* clear chicken3.25:24 */
+ chicken &= 0xFCFFFFFF;
+ /*
+ * if gen1 and B0, set F1020 - if gen 2, do nothing
+ * if gen2 set to F1000
+ */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_GEN);
+ if (pos == 0xC0) {
+ pci_read_config_dword(pdev, pos + 0x10, &control);
+ if ((control & 0x000F0000) != 0x00020000) {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ }
+ printk(KERN_INFO "%s Gen2 strapping detected\n",
+ netxen_nic_driver_name);
+ c8c9value = 0xF1000;
+ } else {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ printk(KERN_INFO "%s Gen1 strapping detected\n",
+ netxen_nic_driver_name);
+ if (adapter->ahw.revision_id == NX_P3_B0)
+ c8c9value = 0xF1020;
+ else
+ c8c9value = 0;
+
+ }
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+
+ if (!c8c9value)
+ return;
+
+ pdevfuncsave = pdev->devfn;
+ if (pdevfuncsave & 0x07)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_write_config_dword(pdev, pos + 8, c8c9value);
+ pdev->devfn++;
+ }
+ pdev->devfn = pdevfuncsave;
+}
+
+static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
+{
+ u32 control;
+ int pos;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ if (pos) {
+ pci_read_config_dword(pdev, pos, &control);
+ if (enable)
+ control |= PCI_MSIX_FLAGS_ENABLE;
+ else
+ control = 0;
+ pci_write_config_dword(pdev, pos, control);
+ }
+}
+
+static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+ adapter->msix_entries[i].entry = i;
+}
+
/*
* netxen_nic_probe()
*
@@ -278,28 +524,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 __iomem *db_ptr = NULL;
- unsigned long mem_base, mem_len, db_base, db_len;
- int pci_using_dac, i = 0, err;
- int ring;
- struct netxen_recv_context *recv_ctx = NULL;
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
- struct netxen_cmd_buffer *cmd_buf_arr = NULL;
+ unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0;
+ int i = 0, err;
+ int first_driver, first_boot;
__le64 mac_addr[FLASH_NUM_PORTS + 1];
- int valid_mac = 0;
u32 val;
int pci_func_id = PCI_FUNC(pdev->devfn);
DECLARE_MAC_BUF(mac);
+ struct netxen_legacy_intr_set *legacy_intrp;
+ uint8_t revision_id;
if (pci_func_id == 0)
- printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+ printk(KERN_INFO "%s\n", netxen_nic_driver_string);
if (pdev->class != 0x020000) {
printk(KERN_DEBUG "NetXen function %d, class %x will not "
"be enabled.\n",pci_func_id, pdev->class);
return -ENODEV;
}
+
if ((err = pci_enable_device(pdev)))
return err;
+
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
err = -ENODEV;
goto err_out_disable_pdev;
@@ -309,18 +555,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
- if (pdev->revision == NX_P2_C1 &&
- (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
- (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
- pci_using_dac = 1;
- } else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
- (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
- goto err_out_free_res;
-
- pci_using_dac = 0;
- }
-
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
@@ -333,13 +567,35 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_NETDEV_DEV(netdev, &pdev->dev);
adapter = netdev->priv;
-
- adapter->ahw.pdev = pdev;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
adapter->ahw.pci_func = pci_func_id;
+ revision_id = pdev->revision;
+ adapter->ahw.revision_id = revision_id;
+
+ err = nx_set_dma_mask(adapter, revision_id);
+ if (err)
+ goto err_out_free_netdev;
+
+ rwlock_init(&adapter->adapter_lock);
+ adapter->ahw.qdr_sn_window = -1;
+ adapter->ahw.ddr_mn_window = -1;
+
/* remap phys address */
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
mem_len = pci_resource_len(pdev, 0);
+ pci_len0 = 0;
+
+ adapter->hw_write_wx = netxen_nic_hw_write_wx_128M;
+ adapter->hw_read_wx = netxen_nic_hw_read_wx_128M;
+ adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M;
+ adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M;
+ adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M;
+ adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M;
+ adapter->pci_set_window = netxen_nic_pci_set_window_128M;
+ adapter->pci_mem_read = netxen_nic_pci_mem_read_128M;
+ adapter->pci_mem_write = netxen_nic_pci_mem_write_128M;
/* 128 Meg of memory */
if (mem_len == NETXEN_PCI_128MB_SIZE) {
@@ -356,27 +612,48 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
first_page_group_start = 0;
first_page_group_end = 0;
+ } else if (mem_len == NETXEN_PCI_2MB_SIZE) {
+ adapter->hw_write_wx = netxen_nic_hw_write_wx_2M;
+ adapter->hw_read_wx = netxen_nic_hw_read_wx_2M;
+ adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M;
+ adapter->pci_write_immediate =
+ netxen_nic_pci_write_immediate_2M;
+ adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M;
+ adapter->pci_write_normalize =
+ netxen_nic_pci_write_normalize_2M;
+ adapter->pci_set_window = netxen_nic_pci_set_window_2M;
+ adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
+ adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
+
+ mem_ptr0 = ioremap(mem_base, mem_len);
+ pci_len0 = mem_len;
+ first_page_group_start = 0;
+ first_page_group_end = 0;
+
+ adapter->ahw.ddr_mn_window = 0;
+ adapter->ahw.qdr_sn_window = 0;
+
+ adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
+ (pci_func_id * 0x20);
+ adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW;
+ if (pci_func_id < 4)
+ adapter->ahw.ms_win_crb += (pci_func_id * 0x20);
+ else
+ adapter->ahw.ms_win_crb +=
+ 0xA0 + ((pci_func_id - 4) * 0x10);
} else {
err = -EIO;
goto err_out_free_netdev;
}
- if ((!mem_ptr0 && mem_len == NETXEN_PCI_128MB_SIZE) ||
- !mem_ptr1 || !mem_ptr2) {
- DPRINTK(ERR,
- "Cannot remap adapter memory aborting.:"
- "0 -> %p, 1 -> %p, 2 -> %p\n",
- mem_ptr0, mem_ptr1, mem_ptr2);
+ dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
- err = -EIO;
- goto err_out_iounmap;
- }
db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
db_len = pci_resource_len(pdev, 4);
if (db_len == 0) {
printk(KERN_ERR "%s: doorbell is disabled\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
@@ -386,13 +663,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
if (!db_ptr) {
printk(KERN_ERR "%s: Failed to allocate doorbell map.",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
adapter->ahw.pci_base0 = mem_ptr0;
+ adapter->ahw.pci_len0 = pci_len0;
adapter->ahw.first_page_group_start = first_page_group_start;
adapter->ahw.first_page_group_end = first_page_group_end;
adapter->ahw.pci_base1 = mem_ptr1;
@@ -400,11 +678,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->ahw.db_base = db_ptr;
adapter->ahw.db_len = db_len;
- adapter->netdev = netdev;
- adapter->pdev = pdev;
-
netif_napi_add(netdev, &adapter->napi,
- netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+ netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+
+ if (revision_id >= NX_P3_B0)
+ legacy_intrp = &legacy_intr[pci_func_id];
+ else
+ legacy_intrp = &legacy_intr[0];
+
+ adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
+ adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
+ adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
+ adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
/* this will be read from FW later */
adapter->intr_scheme = -1;
@@ -414,12 +699,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->portnum = pci_func_id;
adapter->status &= ~NETXEN_NETDEV_STATUS;
adapter->rx_csum = 1;
+ adapter->mc_enabled = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->max_mc_count = 38;
+ adapter->max_rds_rings = 2;
+ } else {
+ adapter->max_mc_count = 16;
+ adapter->max_rds_rings = 3;
+ }
netdev->open = netxen_nic_open;
netdev->stop = netxen_nic_close;
netdev->hard_start_xmit = netxen_nic_xmit_frame;
netdev->get_stats = netxen_nic_get_stats;
- netdev->set_multicast_list = netxen_nic_set_multi;
+ if (NX_IS_REVISION_P3(revision_id))
+ netdev->set_multicast_list = netxen_p3_nic_set_multi;
+ else
+ netdev->set_multicast_list = netxen_p2_nic_set_multi;
netdev->set_mac_address = netxen_nic_set_mac;
netdev->change_mtu = netxen_nic_change_mtu;
netdev->tx_timeout = netxen_tx_timeout;
@@ -435,18 +731,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features = NETIF_F_SG;
netdev->features |= NETIF_F_IP_CSUM;
netdev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ netdev->features |= NETIF_F_IPV6_CSUM;
+ netdev->features |= NETIF_F_TSO6;
+ }
- if (pci_using_dac)
+ if (adapter->pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- if (pci_enable_msi(pdev))
- adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
- else
- adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-
- netdev->irq = pdev->irq;
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
/*
* Set the CRB window to invalid. If any register in window 0 is
* accessed it should set the window to 0 and then reset it to 1.
@@ -455,87 +747,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (netxen_nic_get_board_info(adapter) != 0) {
printk("%s: Error getting board config info.\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
- /*
- * Adapter in our case is quad port so initialize it before
- * initializing the ports
- */
-
netxen_initialize_adapter_ops(adapter);
- adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
- if ((adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB35_4G) ||
- (adapter->ahw.boardcfg.board_type ==
- NETXEN_BRDTYPE_P2_SB31_2G))
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
- else
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
- adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
- adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
-
- cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
- if (cmd_buf_arr == NULL) {
- printk(KERN_ERR
- "%s: Could not allocate cmd_buf_arr memory:%d\n",
- netxen_nic_driver_name, (int)TX_RINGSIZE);
- err = -ENOMEM;
- goto err_out_free_adapter;
- }
- memset(cmd_buf_arr, 0, TX_RINGSIZE);
- adapter->cmd_buf_arr = cmd_buf_arr;
-
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- switch (RCV_DESC_TYPE(ring)) {
- case RCV_DESC_NORMAL:
- rcv_desc->max_rx_desc_count =
- adapter->max_rx_desc_count;
- rcv_desc->flags = RCV_DESC_NORMAL;
- rcv_desc->dma_size = RX_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
- break;
-
- case RCV_DESC_JUMBO:
- rcv_desc->max_rx_desc_count =
- adapter->max_jumbo_rx_desc_count;
- rcv_desc->flags = RCV_DESC_JUMBO;
- rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
- break;
-
- case RCV_RING_LRO:
- rcv_desc->max_rx_desc_count =
- adapter->max_lro_rx_desc_count;
- rcv_desc->flags = RCV_DESC_LRO;
- rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
- break;
-
- }
- rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
- vmalloc(RCV_BUFFSIZE);
-
- if (rcv_desc->rx_buf_arr == NULL) {
- printk(KERN_ERR "%s: Could not allocate "
- "rcv_desc->rx_buf_arr memory:%d\n",
- netxen_nic_driver_name,
- (int)RCV_BUFFSIZE);
- err = -ENOMEM;
- goto err_out_free_rx_buffer;
- }
- memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
- }
-
- }
-
- netxen_initialize_adapter_sw(adapter); /* initialize the buffers in adapter */
-
/* Mezz cards have PCI function 0,2,3 enabled */
switch (adapter->ahw.boardcfg.board_type) {
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -547,90 +765,71 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- init_timer(&adapter->watchdog_timer);
- adapter->ahw.xg_linkup = 0;
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
- adapter->ahw.pdev = pdev;
- adapter->ahw.revision_id = pdev->revision;
-
- /* make sure Window == 1 */
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ /*
+ * This call will setup various max rx/tx counts.
+ * It must be done before any buffer/ring allocations.
+ */
+ netxen_check_options(adapter);
+ first_driver = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if (adapter->ahw.pci_func == 0)
+ first_driver = 1;
+ } else {
+ if (adapter->portnum == 0)
+ first_driver = 1;
+ }
+ adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer = crb_cmd_consumer[adapter->portnum];
netxen_nic_update_cmd_producer(adapter, 0);
netxen_nic_update_cmd_consumer(adapter, 0);
- writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
- if (netxen_is_flash_supported(adapter) == 0 &&
- netxen_get_flash_mac_addr(adapter, mac_addr) == 0)
- valid_mac = 1;
- else
- valid_mac = 0;
-
- if (valid_mac) {
- unsigned char *p = (unsigned char *)&mac_addr[adapter->portnum];
- netdev->dev_addr[0] = *(p + 5);
- netdev->dev_addr[1] = *(p + 4);
- netdev->dev_addr[2] = *(p + 3);
- netdev->dev_addr[3] = *(p + 2);
- netdev->dev_addr[4] = *(p + 1);
- netdev->dev_addr[5] = *(p + 0);
+ if (first_driver) {
+ first_boot = adapter->pci_read_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc));
- memcpy(netdev->perm_addr, netdev->dev_addr,
- netdev->addr_len);
- if (!is_valid_ether_addr(netdev->perm_addr)) {
- printk(KERN_ERR "%s: Bad MAC address %s.\n",
- netxen_nic_driver_name,
- print_mac(mac, netdev->dev_addr));
- } else {
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter,
- netdev->dev_addr);
+ err = netxen_check_hw_init(adapter, first_boot);
+ if (err) {
+ printk(KERN_ERR "%s: error in init HW init sequence\n",
+ netxen_nic_driver_name);
+ goto err_out_iounmap;
}
- }
- if (adapter->portnum == 0) {
- err = netxen_initialize_adapter_offload(adapter);
- if (err)
- goto err_out_free_rx_buffer;
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- if (val == 0x55555555) {
- /* This is the first boot after power up */
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4)) {
- val |= 0x4;
- netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4))
- printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
- netxen_nic_driver_name);
- }
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_SW_RESET));
- printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
- if (val != 0x80000f) {
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
- err = -ENODEV;
- goto err_out_free_dev;
- }
- } else {
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- CRB_CMDPEG_STATE));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_set_port_mode(adapter);
+
+ if (first_boot != 0x55555555) {
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0);
msleep(1);
netxen_load_firmware(adapter);
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
- dev_info(&pdev->dev, "cmdpeg state: 0x%0x\n",
- readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_pcie_strap_init(adapter);
+
+ if (NX_IS_REVISION_P2(revision_id)) {
+
+ /* Initialize multicast addr pool owners */
+ val = 0x7654;
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+ val |= 0x0f000000;
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MAC_ADDR_CNTL_REG, val);
+
+ }
+
+ if ((first_boot == 0x55555555) &&
+ (NX_IS_REVISION_P2(revision_id))) {
+ /* Unlock the HW, prompting the boot sequence */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+
+ err = netxen_initialize_adapter_offload(adapter);
+ if (err)
+ goto err_out_iounmap;
/*
* Tell the hardware our version number.
@@ -638,24 +837,101 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i = (_NETXEN_NIC_LINUX_MAJOR << 16)
| ((_NETXEN_NIC_LINUX_MINOR << 8))
| (_NETXEN_NIC_LINUX_SUBVERSION);
- writel(i, NETXEN_CRB_NORMALIZE(adapter, CRB_DRIVER_VERSION));
+ adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
- /* Unlock the HW, prompting the boot sequence */
- writel(1,
- NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
/* Handshake with the card before we register the devices. */
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+ } /* first_driver */
+
+ netxen_nic_flash_print(adapter);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_MIU_MN_CONTROL, &val, 4);
+ adapter->ahw.cut_through = (val & 0x4) ? 1 : 0;
+ dev_info(&pdev->dev, "firmware running in %s mode\n",
+ adapter->ahw.cut_through ? "cut through" : "legacy");
}
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
adapter->physical_port = adapter->portnum;
- i = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_V2P(adapter->portnum)));
+ i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum));
if (i != 0x55555555)
adapter->physical_port = i;
+ adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+
+ netxen_set_msix_bit(pdev, 0);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if ((mem_len != NETXEN_PCI_128MB_SIZE) &&
+ mem_len != NETXEN_PCI_2MB_SIZE)
+ adapter->msix_supported = 0;
+ }
+
+ if (adapter->msix_supported) {
+
+ netxen_init_msix_entries(adapter);
+
+ if (pci_enable_msix(pdev, adapter->msix_entries,
+ MSIX_ENTRIES_PER_ADAPTER))
+ goto request_msi;
+
+ adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+ netxen_set_msix_bit(pdev, 1);
+ dev_info(&pdev->dev, "using msi-x interrupts\n");
+
+ } else {
+request_msi:
+ if (use_msi && !pci_enable_msi(pdev)) {
+ adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+ dev_info(&pdev->dev, "using msi interrupts\n");
+ } else
+ dev_info(&pdev->dev, "using legacy interrupts\n");
+ }
+
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ netdev->irq = adapter->msix_entries[0].vector;
+ else
+ netdev->irq = pdev->irq;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err)
+ goto err_out_disable_msi;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->ahw.linkup = 0;
+ adapter->watchdog_timer.function = &netxen_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
+ INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
+
+ if (netxen_is_flash_supported(adapter) == 0 &&
+ netxen_get_flash_mac_addr(adapter, mac_addr) == 0) {
+ unsigned char *p;
+
+ p = (unsigned char *)&mac_addr[adapter->portnum];
+ netdev->dev_addr[0] = *(p + 5);
+ netdev->dev_addr[1] = *(p + 4);
+ netdev->dev_addr[2] = *(p + 3);
+ netdev->dev_addr[3] = *(p + 2);
+ netdev->dev_addr[4] = *(p + 1);
+ netdev->dev_addr[5] = *(p + 0);
+
+ memcpy(netdev->perm_addr, netdev->dev_addr,
+ netdev->addr_len);
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+ printk(KERN_ERR "%s: Bad MAC address %s.\n",
+ netxen_nic_driver_name,
+ print_mac(mac, netdev->dev_addr));
+ } else {
+ adapter->macaddr_set(adapter, netdev->dev_addr);
+ }
+ }
+
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -664,41 +940,37 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
" aborting\n", netxen_nic_driver_name,
adapter->portnum);
err = -EIO;
- goto err_out_free_dev;
+ goto err_out_disable_msi;
}
- netxen_nic_flash_print(adapter);
pci_set_drvdata(pdev, adapter);
- return 0;
-
-err_out_free_dev:
- if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
-
-err_out_free_rx_buffer:
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- if (rcv_desc->rx_buf_arr != NULL) {
- vfree(rcv_desc->rx_buf_arr);
- rcv_desc->rx_buf_arr = NULL;
- }
- }
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
+ adapter->netdev->name);
+ break;
+ case NETXEN_NIC_XGBE:
+ dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
+ adapter->netdev->name);
+ break;
}
- vfree(cmd_buf_arr);
-err_out_free_adapter:
+ return 0;
+
+err_out_disable_msi:
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
+ if (first_driver)
+ netxen_free_adapter_offload(adapter);
+err_out_iounmap:
if (db_ptr)
iounmap(db_ptr);
-err_out_iounmap:
if (mem_ptr0)
iounmap(mem_ptr0);
if (mem_ptr1)
@@ -713,6 +985,7 @@ err_out_free_res:
pci_release_regions(pdev);
err_out_disable_pdev:
+ pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
}
@@ -721,11 +994,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
{
struct netxen_adapter *adapter;
struct net_device *netdev;
- struct netxen_rx_buffer *buffer;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int i, ctxid, ring;
- static int init_firmware_done = 0;
adapter = pci_get_drvdata(pdev);
if (adapter == NULL)
@@ -736,36 +1004,18 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- init_firmware_done++;
netxen_free_hw_resources(adapter);
+ netxen_free_sw_resources(adapter);
}
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- recv_ctx = &adapter->recv_ctx[ctxid];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
- buffer = &(rcv_desc->rx_buf_arr[i]);
- if (buffer->state == NETXEN_BUFFER_FREE)
- continue;
- pci_unmap_single(pdev, buffer->dma,
- rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
- if (buffer->skb != NULL)
- dev_kfree_skb_any(buffer->skb);
- }
- vfree(rcv_desc->rx_buf_arr);
- }
- }
-
- vfree(adapter->cmd_buf_arr);
-
if (adapter->portnum == 0)
netxen_free_adapter_offload(adapter);
if (adapter->irq)
free_irq(adapter->irq, adapter);
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
@@ -803,51 +1053,69 @@ static int netxen_nic_open(struct net_device *netdev)
return -EIO;
}
- /* setup all the resources for the Phantom... */
- /* this include the descriptors for rcv, tx, and status */
- netxen_nic_clear_stats(adapter);
- err = netxen_nic_hw_resources(adapter);
+ err = netxen_alloc_sw_resources(adapter);
if (err) {
- printk(KERN_ERR "Error in setting hw resources:%d\n",
- err);
+ printk(KERN_ERR "%s: Error in setting sw resources\n",
+ netdev->name);
return err;
}
+
+ netxen_nic_clear_stats(adapter);
+
+ err = netxen_alloc_hw_resources(adapter);
+ if (err) {
+ printk(KERN_ERR "%s: Error in setting hw resources\n",
+ netdev->name);
+ goto err_out_free_sw;
+ }
+
+ if (adapter->fw_major < 4) {
+ adapter->crb_addr_cmd_producer =
+ crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer =
+ crb_cmd_consumer[adapter->portnum];
+ }
+
+ netxen_nic_update_cmd_producer(adapter, 0);
+ netxen_nic_update_cmd_consumer(adapter, 0);
+
for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers(adapter, ctx, ring);
}
- adapter->irq = adapter->ahw.pdev->irq;
- if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+ if (NETXEN_IS_MSI_FAMILY(adapter))
handler = netxen_msi_intr;
else {
flags |= IRQF_SHARED;
handler = netxen_intr;
}
+ adapter->irq = netdev->irq;
err = request_irq(adapter->irq, handler,
flags, netdev->name, adapter);
if (err) {
printk(KERN_ERR "request_irq failed with: %d\n", err);
- netxen_free_hw_resources(adapter);
- return err;
+ goto err_out_free_hw;
}
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
}
+
/* Done here again so that even if phantom sw overwrote it,
* we set it */
- if (adapter->init_port
- && adapter->init_port(adapter, adapter->portnum) != 0) {
+ err = adapter->init_port(adapter, adapter->physical_port);
+ if (err) {
printk(KERN_ERR "%s: Failed to initialize port %d\n",
netxen_nic_driver_name, adapter->portnum);
- return -EIO;
+ goto err_out_free_irq;
}
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, netdev->dev_addr);
+ adapter->macaddr_set(adapter, netdev->dev_addr);
netxen_nic_set_link_parameters(adapter);
- netxen_nic_set_multi(netdev);
- if (adapter->set_mtu)
+ netdev->set_multicast_list(netdev);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, netdev->mtu);
+ else
adapter->set_mtu(adapter, netdev->mtu);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -858,6 +1126,14 @@ static int netxen_nic_open(struct net_device *netdev)
netif_start_queue(netdev);
return 0;
+
+err_out_free_irq:
+ free_irq(adapter->irq, adapter);
+err_out_free_hw:
+ netxen_free_hw_resources(adapter);
+err_out_free_sw:
+ netxen_free_sw_resources(adapter);
+ return err;
}
/*
@@ -866,9 +1142,6 @@ static int netxen_nic_open(struct net_device *netdev)
static int netxen_nic_close(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- int i, j;
- struct netxen_cmd_buffer *cmd_buff;
- struct netxen_skb_frag *buffrag;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -879,30 +1152,8 @@ static int netxen_nic_close(struct net_device *netdev)
netxen_nic_disable_int(adapter);
- cmd_buff = adapter->cmd_buf_arr;
- for (i = 0; i < adapter->max_tx_desc_count; i++) {
- buffrag = cmd_buff->frag_array;
- if (buffrag->dma) {
- pci_unmap_single(adapter->pdev, buffrag->dma,
- buffrag->length, PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- for (j = 0; j < cmd_buff->frag_count; j++) {
- buffrag++;
- if (buffrag->dma) {
- pci_unmap_page(adapter->pdev, buffrag->dma,
- buffrag->length,
- PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- }
- /* Free the skb we received in netxen_nic_xmit_frame */
- if (cmd_buff->skb) {
- dev_kfree_skb_any(cmd_buff->skb);
- cmd_buff->skb = NULL;
- }
- cmd_buff++;
- }
+ netxen_release_tx_buffers(adapter);
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
FLUSH_SCHEDULED_WORK();
del_timer_sync(&adapter->watchdog_timer);
@@ -911,6 +1162,31 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
+void netxen_tso_check(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *desc, struct sk_buff *skb)
+{
+ if (desc->mss) {
+ desc->total_hdr_length = (sizeof(struct ethhdr) +
+ ip_hdrlen(skb) + tcp_hdrlen(skb));
+
+ if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
+ (skb->protocol == htons(ETH_P_IPV6)))
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
+ else
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
+ else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
+ else
+ return;
+ }
+ desc->tcp_hdr_offset = skb_transport_offset(skb);
+ desc->ip_hdr_offset = skb_network_offset(skb);
+}
+
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -932,7 +1208,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
- if (netdev->features & NETIF_F_TSO) {
+ if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
if (skb_shinfo(skb)->gso_size > 0) {
no_of_desc++;
@@ -959,7 +1235,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
/* Take skb->data itself */
pbuf = &adapter->cmd_buf_arr[producer];
- if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
pbuf->mss = skb_shinfo(skb)->gso_size;
hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
} else {
@@ -1086,6 +1363,89 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
+static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ uint32_t temp, temp_state, temp_val;
+ int rv = 0;
+
+ temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+
+ temp_state = nx_get_temp_state(temp);
+ temp_val = nx_get_temp_val(temp);
+
+ if (temp_state == NX_TEMP_PANIC) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C exceeds"
+ " maximum allowed. Hardware has been shut down.\n",
+ netxen_nic_driver_name, temp_val);
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ rv = 1;
+ } else if (temp_state == NX_TEMP_WARN) {
+ if (adapter->temp == NX_TEMP_NORMAL) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C "
+ "exceeds operating range."
+ " Immediate action needed.\n",
+ netxen_nic_driver_name, temp_val);
+ }
+ } else {
+ if (adapter->temp == NX_TEMP_WARN) {
+ printk(KERN_INFO
+ "%s: Device temperature is now %d degrees C"
+ " in normal range.\n", netxen_nic_driver_name,
+ temp_val);
+ }
+ }
+ adapter->temp = temp_state;
+ return rv;
+}
+
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u32 val, port, linkup;
+
+ port = adapter->physical_port;
+
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+ linkup = (val >> port) & 1;
+ } else {
+ if (adapter->fw_major < 4) {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE);
+ val = (val >> port*8) & 0xff;
+ linkup = (val == XG_LINK_UP);
+ } else {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE_P3);
+ val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+ linkup = (val == XG_LINK_UP_P3);
+ }
+ }
+
+ if (adapter->ahw.linkup && !linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is down\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else if (!adapter->ahw.linkup && linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is up\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 1;
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
@@ -1093,6 +1453,19 @@ static void netxen_watchdog(unsigned long v)
SCHEDULE_WORK(&adapter->watchdog_task);
}
+void netxen_watchdog_task(struct work_struct *work)
+{
+ struct netxen_adapter *adapter =
+ container_of(work, struct netxen_adapter, watchdog_task);
+
+ if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
+ return;
+
+ netxen_nic_handle_phy_intr(adapter);
+
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)
@@ -1118,6 +1491,38 @@ static void netxen_tx_timeout_task(struct work_struct *work)
netif_wake_queue(adapter->netdev);
}
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct net_device_stats *stats = &adapter->net_stats;
+
+ memset(stats, 0, sizeof(*stats));
+
+ /* total packets received */
+ stats->rx_packets = adapter->stats.no_rcv;
+ /* total packets transmitted */
+ stats->tx_packets = adapter->stats.xmitedframes +
+ adapter->stats.xmitfinished;
+ /* total bytes received */
+ stats->rx_bytes = adapter->stats.rxbytes;
+ /* total bytes transmitted */
+ stats->tx_bytes = adapter->stats.txbytes;
+ /* bad packets received */
+ stats->rx_errors = adapter->stats.rcvdbadskb;
+ /* packet transmit problems */
+ stats->tx_errors = adapter->stats.nocmddescriptor;
+ /* no space in linux buffers */
+ stats->rx_dropped = adapter->stats.rxdropped;
+ /* no space available in linux */
+ stats->tx_dropped = adapter->stats.txdropped;
+
+ return stats;
+}
+
static inline void
netxen_handle_int(struct netxen_adapter *adapter)
{
@@ -1125,20 +1530,20 @@ netxen_handle_int(struct netxen_adapter *adapter)
napi_schedule(&adapter->napi);
}
-irqreturn_t netxen_intr(int irq, void *data)
+static irqreturn_t netxen_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
u32 our_int = 0;
- our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
/* not our interrupt */
if ((our_int & (0x80 << adapter->portnum)) == 0)
return IRQ_NONE;
if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
/* claim interrupt */
- writel(our_int & ~((u32)(0x80 << adapter->portnum)),
- NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter, CRB_INT_VECTOR,
+ our_int & ~((u32)(0x80 << adapter->portnum)));
}
netxen_handle_int(adapter);
@@ -1146,7 +1551,7 @@ irqreturn_t netxen_intr(int irq, void *data)
return IRQ_HANDLED;
}
-irqreturn_t netxen_msi_intr(int irq, void *data)
+static irqreturn_t netxen_msi_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
@@ -1220,10 +1625,6 @@ module_init(netxen_init_module);
static void __exit netxen_exit_module(void)
{
- /*
- * Wait for some time to allow the dma to drain, if any.
- */
- msleep(100);
pci_unregister_driver(&netxen_driver);
destroy_workqueue(netxen_workq);
}
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index a3bc7cc67a6..4cb8f4a1cf4 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -46,9 +46,8 @@ static int phy_lock(struct netxen_adapter *adapter)
int done = 0, timeout = 0;
while (!done) {
- done =
- readl(pci_base_offset
- (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
+ done = netxen_nic_reg_read(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
if (done == 1)
break;
if (timeout >= phy_lock_timeout) {
@@ -63,14 +62,14 @@ static int phy_lock(struct netxen_adapter *adapter)
}
}
- writel(PHY_LOCK_DRIVER,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
return 0;
}
static int phy_unlock(struct netxen_adapter *adapter)
{
- readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
+ adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
return 0;
}
@@ -109,7 +108,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
* so it cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -119,7 +118,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
netxen_gb_rx_reset_pb(temp);
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -129,22 +128,22 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
/* send read command */
netxen_gb_mii_mgmt_set_read_cycle(command);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -154,7 +153,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
&& (timeout++ < NETXEN_NIU_PHY_WAITMAX));
if (timeout < NETXEN_NIU_PHY_WAITMAX) {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_STATUS(0),
readval, 4))
return -EIO;
@@ -163,7 +162,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
result = -1;
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -201,7 +200,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
* cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -212,7 +211,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -220,24 +219,24 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
}
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
&val, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -252,7 +251,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
/* restore the state of port 0 MAC in case we tampered with it */
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -401,14 +400,16 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
{
int result = 0;
__u32 status;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return 0;
+
if (adapter->disable_phy_interrupts)
adapter->disable_phy_interrupts(adapter);
mdelay(2);
- if (0 ==
- netxen_niu_gbe_phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- &status)) {
+ if (0 == netxen_niu_gbe_phy_read(adapter,
+ NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) {
if (netxen_get_phy_link(status)) {
if (netxen_get_phy_speed(status) == 2) {
netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -456,12 +457,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
- u32 portnum = adapter->physical_port;
-
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
+ }
return 0;
}
@@ -581,10 +582,10 @@ static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
if ((phy < 0) || (phy > 3))
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -613,14 +614,14 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
temp[0] = temp[1] = 0;
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
return -EIO;
memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
return -2;
netxen_niu_macaddr_get(adapter,
@@ -654,7 +655,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg0 = 0;
@@ -666,7 +667,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_tx_reset_mac(mac_cfg0);
netxen_gb_rx_reset_mac(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg1 = 0;
@@ -679,7 +680,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
if (mode == NETXEN_NIU_10_100_MB) {
netxen_gb_set_intfmode(mac_cfg1, 1);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -692,7 +693,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
} else if (mode == NETXEN_NIU_1000_MB) {
netxen_gb_set_intfmode(mac_cfg1, 2);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -704,7 +705,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
}
mii_cfg = 0;
netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
&mii_cfg, 4))
return -EIO;
mac_cfg0 = 0;
@@ -713,7 +714,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_unset_rx_flowctl(mac_cfg0);
netxen_gb_unset_tx_flowctl(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -730,7 +731,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -746,7 +747,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg = 0;
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
return -EIO;
return 0;
@@ -763,7 +764,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EINVAL;
/* save previous contents */
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE) {
@@ -801,7 +802,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EIO;
}
}
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
return 0;
@@ -826,13 +827,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 0:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -840,13 +841,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 1:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -877,10 +878,10 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
if (phy != 0)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -901,7 +902,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE)
@@ -909,6 +910,11 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
else
reg = (reg & ~0x2000UL);
+ if (mode == NETXEN_NIU_ALLMULTI_MODE)
+ reg = (reg | 0x1000UL);
+ else
+ reg = (reg & ~0x1000UL);
+
netxen_crb_writelit_adapter(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index a566b50f36f..3bfa51b62a4 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -42,8 +42,11 @@
#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c)
#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */
#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14)
-#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x18) /* host add:cmd ring */
-#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x1c)
+#define NX_CDRP_CRB_OFFSET NETXEN_NIC_REG(0x18)
+#define NX_ARG1_CRB_OFFSET NETXEN_NIC_REG(0x1c)
+#define NX_ARG2_CRB_OFFSET NETXEN_NIC_REG(0x20)
+#define NX_ARG3_CRB_OFFSET NETXEN_NIC_REG(0x24)
+#define NX_SIGN_CRB_OFFSET NETXEN_NIC_REG(0x28)
#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) /* 4 regs for perf */
#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24)
#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28)
@@ -73,8 +76,8 @@
#define CRB_RX_LRO_MID_TIMER NETXEN_NIC_REG(0x88)
#define CRB_DMA_MAX_RCV_BUFS NETXEN_NIC_REG(0x8c)
#define CRB_MAX_DMA_ENTRIES NETXEN_NIC_REG(0x90)
-#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */
-#define CRB_AGENT_GO NETXEN_NIC_REG(0x98) /* NIC pkt gen agent */
+#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */
+#define CRB_XG_STATE_P3 NETXEN_NIC_REG(0x98) /* XG PF Link status */
#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0x9c)
#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0)
#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4)
@@ -97,7 +100,9 @@
#define CRB_HOST_BUFFER_CONS NETXEN_NIC_REG(0xf0)
#define CRB_JUMBO_BUFFER_PROD NETXEN_NIC_REG(0xf4)
#define CRB_JUMBO_BUFFER_CONS NETXEN_NIC_REG(0xf8)
+#define CRB_HOST_DUMMY_BUF NETXEN_NIC_REG(0xfc)
+#define CRB_RCVPEG_STATE NETXEN_NIC_REG(0x13c)
#define CRB_CMD_PRODUCER_OFFSET_1 NETXEN_NIC_REG(0x1ac)
#define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0)
#define CRB_CMD_PRODUCER_OFFSET_2 NETXEN_NIC_REG(0x1b8)
@@ -147,29 +152,15 @@
#define nx_get_temp_state(x) ((x) & 0xffff)
#define nx_encode_temp(val, state) (((val) << 16) | (state))
-/* CRB registers per Rcv Descriptor ring */
-struct netxen_rcv_desc_crb {
- u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
- u32 crb_rcv_consumer_offset;
- u32 crb_globalrcv_ring;
- u32 crb_rcv_ring_size;
-};
-
/*
* CRB registers used by the receive peg logic.
*/
struct netxen_recv_crb {
- struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
- u32 crb_rcvstatus_ring;
- u32 crb_rcv_status_producer;
- u32 crb_rcv_status_consumer;
- u32 crb_rcvpeg_state;
- u32 crb_status_ring_size;
+ u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
+ u32 crb_sts_consumer;
};
-extern struct netxen_recv_crb recv_crb_registers[];
-
/*
* Temperature control.
*/
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 32a8503a7ac..4aa54794704 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -158,11 +158,10 @@ static int m88e1111_config_init(struct phy_device *phydev)
{
int err;
int temp;
- int mode;
/* Enable Fiber/Copper auto selection */
temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
- temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
+ temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
temp = phy_read(phydev, MII_BMCR);
@@ -198,9 +197,7 @@ static int m88e1111_config_init(struct phy_device *phydev)
temp &= ~(MII_M1111_HWCFG_MODE_MASK);
- mode = phy_read(phydev, MII_M1111_PHY_EXT_CR);
-
- if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES)
+ if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
else
temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 6b1d7a8edf1..739b3ab7bcc 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -866,7 +866,8 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
+ device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
+ NULL, "ppp");
}
out:
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 504a48ff73c..6531ff565c5 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -50,8 +50,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.16"
-#define DRV_RELDATE "10Nov2007"
+#define DRV_VERSION "0.18"
+#define DRV_RELDATE "13Jul2008"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -91,6 +91,14 @@
#define MISR 0x3C /* Status register */
#define MIER 0x40 /* INT enable register */
#define MSK_INT 0x0000 /* Mask off interrupts */
+#define RX_FINISH 0x0001 /* RX finished */
+#define RX_NO_DESC 0x0002 /* No RX descriptor available */
+#define RX_FIFO_FULL 0x0004 /* RX FIFO full */
+#define RX_EARLY 0x0008 /* RX early */
+#define TX_FINISH 0x0010 /* TX finished */
+#define TX_EARLY 0x0080 /* TX early */
+#define EVENT_OVRFL 0x0100 /* Event counter overflow */
+#define LINK_CHANGED 0x0200 /* PHY link changed */
#define ME_CISR 0x44 /* Event counter INT status */
#define ME_CIER 0x48 /* Event counter INT enable */
#define MR_CNT 0x50 /* Successfully received packet counter */
@@ -130,6 +138,21 @@
#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register */
#define MCAST_MAX 4 /* Max number multicast addresses to filter */
+/* Descriptor status */
+#define DSC_OWNER_MAC 0x8000 /* MAC is the owner of this descriptor */
+#define DSC_RX_OK 0x4000 /* RX was successful */
+#define DSC_RX_ERR 0x0800 /* RX PHY error */
+#define DSC_RX_ERR_DRI 0x0400 /* RX dribble packet */
+#define DSC_RX_ERR_BUF 0x0200 /* RX length exceeds buffer size */
+#define DSC_RX_ERR_LONG 0x0100 /* RX length > maximum packet length */
+#define DSC_RX_ERR_RUNT 0x0080 /* RX packet length < 64 byte */
+#define DSC_RX_ERR_CRC 0x0040 /* RX CRC error */
+#define DSC_RX_BCAST 0x0020 /* RX broadcast (no error) */
+#define DSC_RX_MCAST 0x0010 /* RX multicast (no error) */
+#define DSC_RX_MCH_HIT 0x0008 /* RX multicast hit in hash table (no error) */
+#define DSC_RX_MIDH_HIT 0x0004 /* RX MID table hit (no error) */
+#define DSC_RX_IDX_MID_MASK 3 /* RX mask for the index of matched MIDx */
+
/* PHY settings */
#define ICPLUS_PHY_ID 0x0243
@@ -139,10 +162,10 @@ MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>,"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
-#define RX_INT 0x0001
-#define TX_INT 0x0010
-#define RX_NO_DESC_INT 0x0002
-#define INT_MASK (RX_INT | TX_INT)
+/* RX and TX interrupts that we handle */
+#define RX_INTS (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
+#define TX_INTS (TX_FINISH)
+#define INT_MASK (RX_INTS | TX_INTS)
struct r6040_descriptor {
u16 status, len; /* 0-3 */
@@ -167,7 +190,7 @@ struct r6040_private {
struct r6040_descriptor *tx_ring;
dma_addr_t rx_ring_dma;
dma_addr_t tx_ring_dma;
- u16 tx_free_desc, rx_free_desc, phy_addr, phy_mode;
+ u16 tx_free_desc, phy_addr, phy_mode;
u16 mcr0, mcr1;
u16 switch_sig;
struct net_device *dev;
@@ -183,7 +206,7 @@ static char version[] __devinitdata = KERN_INFO DRV_NAME
static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
/* Read a word data from PHY Chip */
-static int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
+static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
{
int limit = 2048;
u16 cmd;
@@ -200,7 +223,7 @@ static int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
}
/* Write a word data from PHY Chip */
-static void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
{
int limit = 2048;
u16 cmd;
@@ -216,20 +239,20 @@ static void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
}
}
-static int mdio_read(struct net_device *dev, int mii_id, int reg)
+static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- return (phy_read(ioaddr, lp->phy_addr, reg));
+ return (r6040_phy_read(ioaddr, lp->phy_addr, reg));
}
-static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- phy_write(ioaddr, lp->phy_addr, reg, val);
+ r6040_phy_write(ioaddr, lp->phy_addr, reg, val);
}
static void r6040_free_txbufs(struct net_device *dev)
@@ -283,58 +306,101 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring,
desc->vndescp = desc_ring;
}
-/* Allocate skb buffer for rx descriptor */
-static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev)
+static void r6040_init_txbufs(struct net_device *dev)
{
- struct r6040_descriptor *descptr;
- void __iomem *ioaddr = lp->base;
+ struct r6040_private *lp = netdev_priv(dev);
- descptr = lp->rx_insert_ptr;
- while (lp->rx_free_desc < RX_DCNT) {
- descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ lp->tx_free_desc = TX_DCNT;
- if (!descptr->skb_ptr)
- break;
- descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
- descptr->skb_ptr->data,
- MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
- descptr->status = 0x8000;
- descptr = descptr->vndescp;
- lp->rx_free_desc++;
- /* Trigger RX DMA */
- iowrite16(lp->mcr0 | 0x0002, ioaddr);
- }
- lp->rx_insert_ptr = descptr;
+ lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
+ r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
}
-static void r6040_alloc_txbufs(struct net_device *dev)
+static int r6040_alloc_rxbufs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
- void __iomem *ioaddr = lp->base;
+ struct r6040_descriptor *desc;
+ struct sk_buff *skb;
+ int rc;
- lp->tx_free_desc = TX_DCNT;
+ lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
+ r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
- lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
- r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
+ /* Allocate skbs for the rx descriptors */
+ desc = lp->rx_ring;
+ do {
+ skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!skb) {
+ printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ desc->skb_ptr = skb;
+ desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->status = DSC_OWNER_MAC;
+ desc = desc->vndescp;
+ } while (desc != lp->rx_ring);
- iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
- iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+ return 0;
+
+err_exit:
+ /* Deallocate all previously allocated skbs */
+ r6040_free_rxbufs(dev);
+ return rc;
}
-static void r6040_alloc_rxbufs(struct net_device *dev)
+static void r6040_init_mac_regs(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
+ int limit = 2048;
+ u16 cmd;
- lp->rx_free_desc = 0;
+ /* Mask Off Interrupt */
+ iowrite16(MSK_INT, ioaddr + MIER);
- lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
- r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
+ /* Reset RDC MAC */
+ iowrite16(MAC_RST, ioaddr + MCR1);
+ while (limit--) {
+ cmd = ioread16(ioaddr + MCR1);
+ if (cmd & 0x1)
+ break;
+ }
+ /* Reset internal state machine */
+ iowrite16(2, ioaddr + MAC_SM);
+ iowrite16(0, ioaddr + MAC_SM);
+ udelay(5000);
- rx_buf_alloc(lp, dev);
+ /* MAC Bus Control Register */
+ iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
+
+ /* Buffer Size Register */
+ iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
+
+ /* Write TX ring start address */
+ iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
+ iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+ /* Write RX ring start address */
iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0);
iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1);
+
+ /* Set interrupt waiting time and packet numbers */
+ iowrite16(0, ioaddr + MT_ICR);
+ iowrite16(0, ioaddr + MR_ICR);
+
+ /* Enable interrupts */
+ iowrite16(INT_MASK, ioaddr + MIER);
+
+ /* Enable TX and RX */
+ iowrite16(lp->mcr0 | 0x0002, ioaddr);
+
+ /* Let TX poll the descriptors
+ * we may got called by r6040_tx_timeout which has left
+ * some unsent tx buffers */
+ iowrite16(0x01, ioaddr + MTPR);
}
static void r6040_tx_timeout(struct net_device *dev)
@@ -342,27 +408,16 @@ static void r6040_tx_timeout(struct net_device *dev)
struct r6040_private *priv = netdev_priv(dev);
void __iomem *ioaddr = priv->base;
- printk(KERN_WARNING "%s: transmit timed out, status %4.4x, PHY status "
- "%4.4x\n",
+ printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
+ "status %4.4x, PHY status %4.4x\n",
dev->name, ioread16(ioaddr + MIER),
- mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
-
- disable_irq(dev->irq);
- napi_disable(&priv->napi);
- spin_lock(&priv->lock);
- /* Clear all descriptors */
- r6040_free_txbufs(dev);
- r6040_free_rxbufs(dev);
- r6040_alloc_txbufs(dev);
- r6040_alloc_rxbufs(dev);
-
- /* Reset MAC */
- iowrite16(MAC_RST, ioaddr + MCR1);
- spin_unlock(&priv->lock);
- enable_irq(dev->irq);
+ ioread16(ioaddr + MISR),
+ r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
dev->stats.tx_errors++;
- netif_wake_queue(dev);
+
+ /* Reset MAC and re-init all registers */
+ r6040_init_mac_regs(dev);
}
static struct net_device_stats *r6040_get_stats(struct net_device *dev)
@@ -424,6 +479,7 @@ static int r6040_close(struct net_device *dev)
del_timer_sync(&lp->timer);
spin_lock_irq(&lp->lock);
+ napi_disable(&lp->napi);
netif_stop_queue(dev);
r6040_down(dev);
spin_unlock_irq(&lp->lock);
@@ -432,23 +488,23 @@ static int r6040_close(struct net_device *dev)
}
/* Status of PHY CHIP */
-static int phy_mode_chk(struct net_device *dev)
+static int r6040_phy_mode_chk(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int phy_dat;
/* PHY Link Status Check */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
if (!(phy_dat & 0x4))
phy_dat = 0x8000; /* Link Failed, full duplex */
/* PHY Chip Auto-Negotiation Status */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
if (phy_dat & 0x0020) {
/* Auto Negotiation Mode */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 5);
- phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5);
+ phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4);
if (phy_dat & 0x140)
/* Force full duplex */
phy_dat = 0x8000;
@@ -456,7 +512,7 @@ static int phy_mode_chk(struct net_device *dev)
phy_dat = 0;
} else {
/* Force Mode */
- phy_dat = phy_read(ioaddr, lp->phy_addr, 0);
+ phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0);
if (phy_dat & 0x100)
phy_dat = 0x8000;
else
@@ -468,12 +524,12 @@ static int phy_mode_chk(struct net_device *dev)
static void r6040_set_carrier(struct mii_if_info *mii)
{
- if (phy_mode_chk(mii->dev)) {
+ if (r6040_phy_mode_chk(mii->dev)) {
/* autoneg is off: Link is always assumed to be up */
if (!netif_carrier_ok(mii->dev))
netif_carrier_on(mii->dev);
} else
- phy_mode_chk(mii->dev);
+ r6040_phy_mode_chk(mii->dev);
}
static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -494,73 +550,72 @@ static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int r6040_rx(struct net_device *dev, int limit)
{
struct r6040_private *priv = netdev_priv(dev);
- int count;
- void __iomem *ioaddr = priv->base;
+ struct r6040_descriptor *descptr = priv->rx_remove_ptr;
+ struct sk_buff *skb_ptr, *new_skb;
+ int count = 0;
u16 err;
- for (count = 0; count < limit; ++count) {
- struct r6040_descriptor *descptr = priv->rx_remove_ptr;
- struct sk_buff *skb_ptr;
-
- /* Disable RX interrupt */
- iowrite16(ioread16(ioaddr + MIER) & (~RX_INT), ioaddr + MIER);
- descptr = priv->rx_remove_ptr;
-
- /* Check for errors */
- err = ioread16(ioaddr + MLSR);
- if (err & 0x0400)
- dev->stats.rx_errors++;
- /* RX FIFO over-run */
- if (err & 0x8000)
- dev->stats.rx_fifo_errors++;
- /* RX descriptor unavailable */
- if (err & 0x0080)
- dev->stats.rx_frame_errors++;
- /* Received packet with length over buffer lenght */
- if (err & 0x0020)
- dev->stats.rx_over_errors++;
- /* Received packet with too long or short */
- if (err & (0x0010 | 0x0008))
- dev->stats.rx_length_errors++;
- /* Received packet with CRC errors */
- if (err & 0x0004) {
- spin_lock(&priv->lock);
- dev->stats.rx_crc_errors++;
- spin_unlock(&priv->lock);
- }
-
- while (priv->rx_free_desc) {
- /* No RX packet */
- if (descptr->status & 0x8000)
- break;
- skb_ptr = descptr->skb_ptr;
- if (!skb_ptr) {
- printk(KERN_ERR "%s: Inconsistent RX"
- "descriptor chain\n",
- dev->name);
- break;
+ /* Limit not reached and the descriptor belongs to the CPU */
+ while (count < limit && !(descptr->status & DSC_OWNER_MAC)) {
+ /* Read the descriptor status */
+ err = descptr->status;
+ /* Global error status set */
+ if (err & DSC_RX_ERR) {
+ /* RX dribble */
+ if (err & DSC_RX_ERR_DRI)
+ dev->stats.rx_frame_errors++;
+ /* Buffer lenght exceeded */
+ if (err & DSC_RX_ERR_BUF)
+ dev->stats.rx_length_errors++;
+ /* Packet too long */
+ if (err & DSC_RX_ERR_LONG)
+ dev->stats.rx_length_errors++;
+ /* Packet < 64 bytes */
+ if (err & DSC_RX_ERR_RUNT)
+ dev->stats.rx_length_errors++;
+ /* CRC error */
+ if (err & DSC_RX_ERR_CRC) {
+ spin_lock(&priv->lock);
+ dev->stats.rx_crc_errors++;
+ spin_unlock(&priv->lock);
}
- descptr->skb_ptr = NULL;
- skb_ptr->dev = priv->dev;
- /* Do not count the CRC */
- skb_put(skb_ptr, descptr->len - 4);
- pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
- MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
- /* Send to upper layer */
- netif_receive_skb(skb_ptr);
- dev->last_rx = jiffies;
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += descptr->len;
- /* To next descriptor */
- descptr = descptr->vndescp;
- priv->rx_free_desc--;
+ goto next_descr;
+ }
+
+ /* Packet successfully received */
+ new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!new_skb) {
+ dev->stats.rx_dropped++;
+ goto next_descr;
}
- priv->rx_remove_ptr = descptr;
+ skb_ptr = descptr->skb_ptr;
+ skb_ptr->dev = priv->dev;
+
+ /* Do not count the CRC */
+ skb_put(skb_ptr, descptr->len - 4);
+ pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
+
+ /* Send to upper layer */
+ netif_receive_skb(skb_ptr);
+ dev->last_rx = jiffies;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += descptr->len - 4;
+
+ /* put new skb into descriptor */
+ descptr->skb_ptr = new_skb;
+ descptr->buf = cpu_to_le32(pci_map_single(priv->pdev,
+ descptr->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+
+next_descr:
+ /* put the descriptor back to the MAC */
+ descptr->status = DSC_OWNER_MAC;
+ descptr = descptr->vndescp;
+ count++;
}
- /* Allocate new RX buffer */
- if (priv->rx_free_desc < RX_DCNT)
- rx_buf_alloc(priv, priv->dev);
+ priv->rx_remove_ptr = descptr;
return count;
}
@@ -584,7 +639,7 @@ static void r6040_tx(struct net_device *dev)
if (err & (0x2000 | 0x4000))
dev->stats.tx_carrier_errors++;
- if (descptr->status & 0x8000)
+ if (descptr->status & DSC_OWNER_MAC)
break; /* Not complete */
skb_ptr = descptr->skb_ptr;
pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
@@ -616,7 +671,7 @@ static int r6040_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
netif_rx_complete(dev, napi);
/* Enable RX interrupt */
- iowrite16(ioread16(ioaddr + MIER) | RX_INT, ioaddr + MIER);
+ iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
}
return work_done;
}
@@ -638,13 +693,22 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
return IRQ_NONE;
/* RX interrupt request */
- if (status & 0x01) {
+ if (status & RX_INTS) {
+ if (status & RX_NO_DESC) {
+ /* RX descriptor unavailable */
+ dev->stats.rx_dropped++;
+ dev->stats.rx_missed_errors++;
+ }
+ if (status & RX_FIFO_FULL)
+ dev->stats.rx_fifo_errors++;
+
+ /* Mask off RX interrupt */
+ iowrite16(ioread16(ioaddr + MIER) & ~RX_INTS, ioaddr + MIER);
netif_rx_schedule(dev, &lp->napi);
- iowrite16(TX_INT, ioaddr + MIER);
}
/* TX interrupt request */
- if (status & 0x10)
+ if (status & TX_INTS)
r6040_tx(dev);
return IRQ_HANDLED;
@@ -660,52 +724,48 @@ static void r6040_poll_controller(struct net_device *dev)
#endif
/* Init RDC MAC */
-static void r6040_up(struct net_device *dev)
+static int r6040_up(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
+ int ret;
/* Initialise and alloc RX/TX buffers */
- r6040_alloc_txbufs(dev);
- r6040_alloc_rxbufs(dev);
+ r6040_init_txbufs(dev);
+ ret = r6040_alloc_rxbufs(dev);
+ if (ret)
+ return ret;
- /* Buffer Size Register */
- iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
/* Read the PHY ID */
- lp->switch_sig = phy_read(ioaddr, 0, 2);
+ lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
if (lp->switch_sig == ICPLUS_PHY_ID) {
- phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
+ r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
lp->phy_mode = 0x8000;
} else {
/* PHY Mode Check */
- phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
- phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
+ r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
+ r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
if (PHY_MODE == 0x3100)
- lp->phy_mode = phy_mode_chk(dev);
+ lp->phy_mode = r6040_phy_mode_chk(dev);
else
lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
}
- /* MAC Bus Control Register */
- iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
- /* MAC TX/RX Enable */
+ /* Set duplex mode */
lp->mcr0 |= lp->phy_mode;
- iowrite16(lp->mcr0, ioaddr);
-
- /* set interrupt waiting time and packet numbers */
- iowrite16(0x0F06, ioaddr + MT_ICR);
- iowrite16(0x0F06, ioaddr + MR_ICR);
/* improve performance (by RDC guys) */
- phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));
- phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));
- phy_write(ioaddr, 0, 19, 0x0000);
- phy_write(ioaddr, 0, 30, 0x01F0);
+ r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
+ r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
+ r6040_phy_write(ioaddr, 0, 19, 0x0000);
+ r6040_phy_write(ioaddr, 0, 30, 0x01F0);
- /* Interrupt Mask Register */
- iowrite16(INT_MASK, ioaddr + MIER);
+ /* Initialize all MAC registers */
+ r6040_init_mac_regs(dev);
+
+ return 0;
}
/*
@@ -721,7 +781,7 @@ static void r6040_timer(unsigned long data)
/* Polling PHY Chip Status */
if (PHY_MODE == 0x3100)
- phy_mode = phy_mode_chk(dev);
+ phy_mode = r6040_phy_mode_chk(dev);
else
phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
@@ -784,7 +844,14 @@ static int r6040_open(struct net_device *dev)
return -ENOMEM;
}
- r6040_up(dev);
+ ret = r6040_up(dev);
+ if (ret) {
+ pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+ lp->tx_ring_dma);
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+ return ret;
+ }
napi_enable(&lp->napi);
netif_start_queue(dev);
@@ -830,7 +897,7 @@ static int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev)
descptr->skb_ptr = skb;
descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
- descptr->status = 0x8000;
+ descptr->status = DSC_OWNER_MAC;
/* Trigger the MAC to check the TX descriptor */
iowrite16(0x01, ioaddr + MTPR);
lp->tx_insert_ptr = descptr->vndescp;
@@ -987,24 +1054,27 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err)
- return err;
+ goto err_out;
/* this should always be supported */
- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
"not supported by the card\n");
- return -ENODEV;
+ goto err_out;
}
- if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
"not supported by the card\n");
- return -ENODEV;
+ goto err_out;
}
/* IO Size check */
if (pci_resource_len(pdev, 0) < io_size) {
- printk(KERN_ERR "Insufficient PCI resources, aborting\n");
- return -EIO;
+ printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n");
+ err = -EIO;
+ goto err_out;
}
pioaddr = pci_resource_start(pdev, 0); /* IO map base address */
@@ -1012,24 +1082,26 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct r6040_private));
if (!dev) {
- printk(KERN_ERR "Failed to allocate etherdev\n");
- return -ENOMEM;
+ printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n");
+ err = -ENOMEM;
+ goto err_out;
}
SET_NETDEV_DEV(dev, &pdev->dev);
lp = netdev_priv(dev);
- lp->pdev = pdev;
- if (pci_request_regions(pdev, DRV_NAME)) {
+ err = pci_request_regions(pdev, DRV_NAME);
+
+ if (err) {
printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
- err = -ENODEV;
- goto err_out_disable;
+ goto err_out_free_dev;
}
ioaddr = pci_iomap(pdev, bar, io_size);
if (!ioaddr) {
printk(KERN_ERR "ioremap failed for device %s\n",
pci_name(pdev));
- return -EIO;
+ err = -EIO;
+ goto err_out_free_res;
}
/* Init system & device */
@@ -1049,6 +1121,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* Link new device into r6040_root_dev */
lp->pdev = pdev;
+ lp->dev = dev;
/* Init RDC private data */
lp->mcr0 = 0x1002;
@@ -1070,8 +1143,8 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
#endif
netif_napi_add(dev, &lp->napi, r6040_poll, 64);
lp->mii_if.dev = dev;
- lp->mii_if.mdio_read = mdio_read;
- lp->mii_if.mdio_write = mdio_write;
+ lp->mii_if.mdio_read = r6040_mdio_read;
+ lp->mii_if.mdio_write = r6040_mdio_write;
lp->mii_if.phy_id = lp->phy_addr;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
@@ -1080,17 +1153,17 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
err = register_netdev(dev);
if (err) {
printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
- goto err_out_res;
+ goto err_out_unmap;
}
return 0;
-err_out_res:
+err_out_unmap:
+ pci_iounmap(pdev, ioaddr);
+err_out_free_res:
pci_release_regions(pdev);
-err_out_disable:
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
+err_out_free_dev:
free_netdev(dev);
-
+err_out:
return err;
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cfe8829ed31..a3e3895e503 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1418,8 +1418,10 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
rtl_hw_phy_config(dev);
- dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
- RTL_W8(0x82, 0x01);
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+ dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+ RTL_W8(0x82, 0x01);
+ }
pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
@@ -3032,13 +3034,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
tmp = rtl8169_rx_config | rx_mode |
(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
- if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_16) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
+ if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
u32 data = mc_filter[0];
mc_filter[0] = swab32(mc_filter[1]);
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7b2015f9e46..45c72eebb3a 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -19,6 +19,7 @@
#include <linux/in.h>
#include <linux/crc32.h>
#include <linux/ethtool.h>
+#include <linux/topology.h>
#include "net_driver.h"
#include "gmii.h"
#include "ethtool.h"
@@ -832,7 +833,23 @@ static void efx_probe_interrupts(struct efx_nic *efx)
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
- efx->rss_queues = rss_cpus ? rss_cpus : num_online_cpus();
+ if (rss_cpus == 0) {
+ cpumask_t core_mask;
+ int cpu;
+
+ cpus_clear(core_mask);
+ efx->rss_queues = 0;
+ for_each_online_cpu(cpu) {
+ if (!cpu_isset(cpu, core_mask)) {
+ ++efx->rss_queues;
+ cpus_or(core_mask, core_mask,
+ topology_core_siblings(cpu));
+ }
+ }
+ } else {
+ efx->rss_queues = rss_cpus;
+ }
+
efx->rss_queues = min(efx->rss_queues, max_channel + 1);
efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
@@ -1762,7 +1779,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
efx->reset_pending = method;
- queue_work(efx->workqueue, &efx->reset_work);
+ queue_work(efx->reset_workqueue, &efx->reset_work);
}
/**************************************************************************
@@ -1907,14 +1924,28 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
goto fail1;
}
+ efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
+ if (!efx->reset_workqueue) {
+ rc = -ENOMEM;
+ goto fail2;
+ }
+
return 0;
+ fail2:
+ destroy_workqueue(efx->workqueue);
+ efx->workqueue = NULL;
+
fail1:
return rc;
}
static void efx_fini_struct(struct efx_nic *efx)
{
+ if (efx->reset_workqueue) {
+ destroy_workqueue(efx->reset_workqueue);
+ efx->reset_workqueue = NULL;
+ }
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
@@ -1977,7 +2008,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
* scheduled from this point because efx_stop_all() has been
* called, we are no longer registered with driverlink, and
* the net_device's have been removed. */
- flush_workqueue(efx->workqueue);
+ flush_workqueue(efx->reset_workqueue);
efx_pci_remove_main(efx);
@@ -2098,7 +2129,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
* scheduled since efx_stop_all() has been called, and we
* have not and never have been registered with either
* the rtnetlink or driverlink layers. */
- cancel_work_sync(&efx->reset_work);
+ flush_workqueue(efx->reset_workqueue);
/* Retry if a recoverably reset event has been scheduled */
if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 630406e142e..9138ee5b7b7 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -223,13 +223,8 @@ static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
.getsda = falcon_getsda,
.getscl = falcon_getscl,
.udelay = 5,
- /*
- * This is the number of system clock ticks after which
- * i2c-algo-bit gives up waiting for SCL to become high.
- * It must be at least 2 since the first tick can happen
- * immediately after it starts waiting.
- */
- .timeout = 2,
+ /* Wait up to 50 ms for slave to let us pull SCL high */
+ .timeout = DIV_ROUND_UP(HZ, 20),
};
/**************************************************************************
@@ -2479,12 +2474,11 @@ int falcon_probe_nic(struct efx_nic *efx)
/* Initialise I2C adapter */
efx->i2c_adap.owner = THIS_MODULE;
- efx->i2c_adap.class = I2C_CLASS_HWMON;
nic_data->i2c_data = falcon_i2c_bit_operations;
nic_data->i2c_data.data = efx;
efx->i2c_adap.algo_data = &nic_data->i2c_data;
efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
- strcpy(efx->i2c_adap.name, "SFC4000 GPIO");
+ strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
rc = i2c_bit_add_bus(&efx->i2c_adap);
if (rc)
goto fail5;
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index d803b86c647..219c74a772c 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -616,7 +616,9 @@ union efx_multicast_hash {
* @pci_dev: The PCI device
* @type: Controller type attributes
* @legacy_irq: IRQ number
- * @workqueue: Workqueue for resets, port reconfigures and the HW monitor
+ * @workqueue: Workqueue for port reconfigures and the HW monitor.
+ * Work items do not hold and must not acquire RTNL.
+ * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL.
* @reset_work: Scheduled reset workitem
* @monitor_work: Hardware monitor workitem
* @membase_phys: Memory BAR value as physical address
@@ -684,6 +686,7 @@ struct efx_nic {
const struct efx_nic_type *type;
int legacy_irq;
struct workqueue_struct *workqueue;
+ struct workqueue_struct *reset_workqueue;
struct work_struct reset_work;
struct delayed_work monitor_work;
resource_size_t membase_phys;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a4bc812aa99..c69ba1395fa 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -642,17 +642,12 @@ static void sh_eth_adjust_link(struct net_device *ndev)
| ECMR_DM, ioaddr + ECMR);
new_state = 1;
mdp->link = phydev->link;
- netif_tx_schedule_all(ndev);
- netif_carrier_on(ndev);
- netif_start_queue(ndev);
}
} else if (mdp->link) {
new_state = 1;
mdp->link = PHY_DOWN;
mdp->speed = 0;
mdp->duplex = -1;
- netif_stop_queue(ndev);
- netif_carrier_off(ndev);
}
if (new_state)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 711e4a8948e..5257cf464f1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1829,9 +1829,6 @@ static int sky2_down(struct net_device *dev)
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
- /* Stop more packets from being queued */
- netif_stop_queue(dev);
-
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
imask &= ~portirq_msk[port];
@@ -1887,8 +1884,6 @@ static int sky2_down(struct net_device *dev)
sky2_phy_power_down(hw, port);
- netif_carrier_off(dev);
-
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index f2051b209da..2040965d772 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -308,7 +308,7 @@ static void smc_reset(struct net_device *dev)
* can't handle it then there will be no recovery except for
* a hard reset or power cycle
*/
- if (nowait)
+ if (lp->cfg.flags & SMC91X_NOWAIT)
cfg |= CONFIG_NO_WAIT;
/*
@@ -1939,8 +1939,11 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
if (retval)
goto err_out;
-#ifdef SMC_USE_PXA_DMA
- {
+#ifdef CONFIG_ARCH_PXA
+# ifdef SMC_USE_PXA_DMA
+ lp->cfg.flags |= SMC91X_USE_DMA;
+# endif
+ if (lp->cfg.flags & SMC91X_USE_DMA) {
int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
smc_pxa_dma_irq, NULL);
if (dma >= 0)
@@ -1980,7 +1983,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr,
}
err_out:
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
if (retval && dev->dma != (unsigned char)-1)
pxa_free_dma(dev->dma);
#endif
@@ -2050,9 +2053,11 @@ static int smc_enable_device(struct platform_device *pdev)
return 0;
}
-static int smc_request_attrib(struct platform_device *pdev)
+static int smc_request_attrib(struct platform_device *pdev,
+ struct net_device *ndev)
{
struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ struct smc_local *lp = netdev_priv(ndev);
if (!res)
return 0;
@@ -2063,9 +2068,11 @@ static int smc_request_attrib(struct platform_device *pdev)
return 0;
}
-static void smc_release_attrib(struct platform_device *pdev)
+static void smc_release_attrib(struct platform_device *pdev,
+ struct net_device *ndev)
{
struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ struct smc_local *lp = netdev_priv(ndev);
if (res)
release_mem_region(res->start, ATTRIB_SIZE);
@@ -2123,27 +2130,14 @@ static int smc_drv_probe(struct platform_device *pdev)
struct net_device *ndev;
struct resource *res, *ires;
unsigned int __iomem *addr;
+ unsigned long irq_flags = SMC_IRQ_FLAGS;
int ret;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
- if (!res)
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENODEV;
- goto out;
- }
-
-
- if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
- ret = -EBUSY;
- goto out;
- }
-
ndev = alloc_etherdev(sizeof(struct smc_local));
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto out_release_io;
+ goto out;
}
SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -2152,37 +2146,47 @@ static int smc_drv_probe(struct platform_device *pdev)
*/
lp = netdev_priv(ndev);
- lp->cfg.irq_flags = SMC_IRQ_FLAGS;
-#ifdef SMC_DYNAMIC_BUS_CONFIG
- if (pd)
+ if (pd) {
memcpy(&lp->cfg, pd, sizeof(lp->cfg));
- else {
- lp->cfg.flags = SMC91X_USE_8BIT;
- lp->cfg.flags |= SMC91X_USE_16BIT;
- lp->cfg.flags |= SMC91X_USE_32BIT;
+ lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
+ } else {
+ lp->cfg.flags |= (SMC_CAN_USE_8BIT) ? SMC91X_USE_8BIT : 0;
+ lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
+ lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
+ lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
}
- lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
- lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
- lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
-#endif
-
ndev->dma = (unsigned char)-1;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto out_free_netdev;
+ }
+
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
+ ret = -EBUSY;
+ goto out_free_netdev;
+ }
+
ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!ires) {
ret = -ENODEV;
- goto out_free_netdev;
+ goto out_release_io;
}
ndev->irq = ires->start;
- if (SMC_IRQ_FLAGS == -1)
- lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
- ret = smc_request_attrib(pdev);
+ if (ires->flags & IRQF_TRIGGER_MASK)
+ irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+
+ ret = smc_request_attrib(pdev, ndev);
if (ret)
- goto out_free_netdev;
+ goto out_release_io;
#if defined(CONFIG_SA1100_ASSABET)
NCR_0 |= NCR_ENET_OSC_EN;
#endif
@@ -2197,7 +2201,7 @@ static int smc_drv_probe(struct platform_device *pdev)
goto out_release_attrib;
}
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
{
struct smc_local *lp = netdev_priv(ndev);
lp->device = &pdev->dev;
@@ -2205,7 +2209,7 @@ static int smc_drv_probe(struct platform_device *pdev)
}
#endif
- ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+ ret = smc_probe(ndev, addr, irq_flags);
if (ret != 0)
goto out_iounmap;
@@ -2217,11 +2221,11 @@ static int smc_drv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
iounmap(addr);
out_release_attrib:
- smc_release_attrib(pdev);
- out_free_netdev:
- free_netdev(ndev);
+ smc_release_attrib(pdev, ndev);
out_release_io:
release_mem_region(res->start, SMC_IO_EXTENT);
+ out_free_netdev:
+ free_netdev(ndev);
out:
printk("%s: not found (%d).\n", CARDNAME, ret);
@@ -2240,14 +2244,14 @@ static int smc_drv_remove(struct platform_device *pdev)
free_irq(ndev->irq, ndev);
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
if (ndev->dma != (unsigned char)-1)
pxa_free_dma(ndev->dma);
#endif
iounmap(lp->base);
smc_release_datacs(pdev,ndev);
- smc_release_attrib(pdev);
+ smc_release_attrib(pdev,ndev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
if (!res)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 8606818653f..22209b6f140 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -40,23 +40,46 @@
* Define your architecture specific bus configuration parameters here.
*/
-#if defined(CONFIG_ARCH_LUBBOCK)
+#if defined(CONFIG_ARCH_LUBBOCK) ||\
+ defined(CONFIG_MACH_MAINSTONE) ||\
+ defined(CONFIG_MACH_ZYLONITE) ||\
+ defined(CONFIG_MACH_LITTLETON)
-/* We can only do 16-bit reads and writes in the static memory space. */
-#define SMC_CAN_USE_8BIT 0
+#include <asm/mach-types.h>
+
+/* Now the bus width is specified in the platform data
+ * pretend here to support all I/O access types
+ */
+#define SMC_CAN_USE_8BIT 1
#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 0
+#define SMC_CAN_USE_32BIT 1
#define SMC_NOWAIT 1
-/* The first two address lines aren't connected... */
-#define SMC_IO_SHIFT 2
+#define SMC_IO_SHIFT (lp->io_shift)
+#define SMC_inb(a, r) readb((a) + (r))
#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
#define SMC_IRQ_FLAGS (-1) /* from resource */
+/* We actually can't write halfwords properly if not word aligned */
+static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+{
+ if (machine_is_mainstone() && reg & 2) {
+ unsigned int v = val << 16;
+ v |= readl(ioaddr + (reg & ~2)) & 0xffff;
+ writel(v, ioaddr + (reg & ~2));
+ } else {
+ writew(val, ioaddr + reg);
+ }
+}
+
#elif defined(CONFIG_BLACKFIN)
#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH
@@ -195,7 +218,6 @@
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
#elif defined(CONFIG_ARCH_INNOKOM) || \
- defined(CONFIG_MACH_MAINSTONE) || \
defined(CONFIG_ARCH_PXA_IDP) || \
defined(CONFIG_ARCH_RAMSES) || \
defined(CONFIG_ARCH_PCM027)
@@ -229,22 +251,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
-#elif defined(CONFIG_MACH_ZYLONITE)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 0
-#define SMC_IO_SHIFT 0
-#define SMC_NOWAIT 1
-#define SMC_USE_PXA_DMA 1
-#define SMC_inb(a, r) readb((a) + (r))
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
-#define SMC_IRQ_FLAGS (-1) /* from resource */
-
#elif defined(CONFIG_ARCH_OMAP)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -454,7 +460,6 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
#define RPC_LSA_DEFAULT RPC_LED_100_10
#define RPC_LSB_DEFAULT RPC_LED_TX_RX
-#define SMC_DYNAMIC_BUS_CONFIG
#endif
@@ -493,7 +498,7 @@ struct smc_local {
spinlock_t lock;
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
/* DMA needs the physical address of the chip */
u_long physaddr;
struct device *device;
@@ -501,20 +506,17 @@ struct smc_local {
void __iomem *base;
void __iomem *datacs;
+ /* the low address lines on some platforms aren't connected... */
+ int io_shift;
+
struct smc91x_platdata cfg;
};
-#ifdef SMC_DYNAMIC_BUS_CONFIG
-#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
-#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
-#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
-#else
-#define SMC_8BIT(p) SMC_CAN_USE_8BIT
-#define SMC_16BIT(p) SMC_CAN_USE_16BIT
-#define SMC_32BIT(p) SMC_CAN_USE_32BIT
-#endif
+#define SMC_8BIT(p) ((p)->cfg.flags & SMC91X_USE_8BIT)
+#define SMC_16BIT(p) ((p)->cfg.flags & SMC91X_USE_16BIT)
+#define SMC_32BIT(p) ((p)->cfg.flags & SMC91X_USE_32BIT)
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
/*
* Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
* always happening in irq context so no need to worry about races. TX is
@@ -608,7 +610,7 @@ smc_pxa_dma_irq(int dma, void *dummy)
{
DCSR(dma) = 0;
}
-#endif /* SMC_USE_PXA_DMA */
+#endif /* CONFIG_ARCH_PXA */
/*
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 1aa425be306..b79d5f018f7 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2377,8 +2377,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
spin_lock_irq(&hp->happy_lock);
- netif_stop_queue(dev);
-
if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
@@ -2410,8 +2408,6 @@ static void happy_meal_set_multicast(struct net_device *dev)
hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
}
- netif_wake_queue(dev);
-
spin_unlock_irq(&hp->happy_lock);
}
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 41d3ac45685..a645e5028c1 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -672,7 +672,6 @@ static void tc_handle_link_change(struct net_device *dev)
if (dev->flags & IFF_PROMISC)
tc35815_set_multicast_list(dev);
#endif
- netif_tx_schedule_all(dev);
} else {
lp->speed = 0;
lp->duplex = -1;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index bc30c6e8fea..617ef41bdfe 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -5514,22 +5514,6 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
netif_wake_queue(dev); /* Unlock the TX ring */
break;
- case DE4X5_SET_PROM: /* Set Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr |= OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags |= IFF_PROMISC;
- break;
-
- case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr &= ~OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags &= ~IFF_PROMISC;
- break;
-
case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
printk("%s: Boo!\n", dev->name);
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index f5f33b3eb06..9f2877438fb 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -1004,8 +1004,7 @@ struct de4x5_ioctl {
*/
#define DE4X5_GET_HWADDR 0x01 /* Get the hardware address */
#define DE4X5_SET_HWADDR 0x02 /* Set the hardware address */
-#define DE4X5_SET_PROM 0x03 /* Set Promiscuous Mode */
-#define DE4X5_CLR_PROM 0x04 /* Clear Promiscuous Mode */
+/* 0x03 and 0x04 were used before and are obsoleted now. Don't use them. */
#define DE4X5_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */
#define DE4X5_GET_MCA 0x06 /* Get a multicast address */
#define DE4X5_SET_MCA 0x07 /* Set a multicast address */
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a82b32b4013..e6bbc639c2d 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -900,7 +900,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
return -EINVAL;
rtnl_lock();
- ret = update_filter(&tun->txflt, (void *) __user arg);
+ ret = update_filter(&tun->txflt, (void __user *)arg);
rtnl_unlock();
return ret;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 756ba10b79d..8f944e57fd5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1588,7 +1588,6 @@ static void adjust_link(struct net_device *dev)
if (!ugeth->oldlink) {
new_state = 1;
ugeth->oldlink = 1;
- netif_tx_schedule_all(dev);
}
} else if (ugeth->oldlink) {
new_state = 1;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index a934428a589..0e061dfea78 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -50,10 +50,18 @@ static int is_activesync(struct usb_interface_descriptor *desc)
&& desc->bInterfaceProtocol == 1;
}
+static int is_wireless_rndis(struct usb_interface_descriptor *desc)
+{
+ return desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER
+ && desc->bInterfaceSubClass == 1
+ && desc->bInterfaceProtocol == 3;
+}
+
#else
#define is_rndis(desc) 0
#define is_activesync(desc) 0
+#define is_wireless_rndis(desc) 0
#endif
@@ -110,7 +118,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
* of cdc-acm, it'll fail RNDIS requests cleanly.
*/
rndis = is_rndis(&intf->cur_altsetting->desc)
- || is_activesync(&intf->cur_altsetting->desc);
+ || is_activesync(&intf->cur_altsetting->desc)
+ || is_wireless_rndis(&intf->cur_altsetting->desc);
memset(info, 0, sizeof *info);
info->control = intf;
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 61c98beb4d1..bcd858c567e 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -576,6 +576,10 @@ static const struct usb_device_id products [] = {
/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
.driver_info = (unsigned long) &rndis_info,
+}, {
+ /* RNDIS for tethering */
+ USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3),
+ .driver_info = (unsigned long) &rndis_info,
},
{ }, // END
};
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 5827324e9d9..f7d3349dc3e 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -397,9 +397,9 @@ static int __init cosa_init(void)
err = PTR_ERR(cosa_class);
goto out_chrdev;
}
- for (i=0; i<nr_cards; i++) {
- device_create(cosa_class, NULL, MKDEV(cosa_major, i), "cosa%d", i);
- }
+ for (i = 0; i < nr_cards; i++)
+ device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
+ NULL, "cosa%d", i);
err = 0;
goto out;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 13d5882f1f2..3153fe9d7ce 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3101,6 +3101,7 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
* This is a natural nesting, which needs a split lock type.
*/
static struct lock_class_key hostap_netdev_xmit_lock_key;
+static struct lock_class_key hostap_netdev_addr_lock_key;
static void prism2_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
@@ -3112,6 +3113,8 @@ static void prism2_set_lockdep_class_one(struct net_device *dev,
static void prism2_set_lockdep_class(struct net_device *dev)
{
+ lockdep_set_class(&dev->addr_list_lock,
+ &hostap_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
}
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 6e704608947..1acfbcd3703 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4972,8 +4972,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
}
done:
if ((ipw_tx_queue_space(q) > q->low_mark) &&
- (qindex >= 0) &&
- (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev))
+ (qindex >= 0))
netif_wake_queue(priv->net_dev);
used = q->first_empty - q->last_used;
if (used < 0)
@@ -10154,14 +10153,8 @@ static void init_sys_config(struct ipw_sys_config *sys_config)
static int ipw_net_open(struct net_device *dev)
{
- struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_INFO("dev->open\n");
- /* we should be verifying the device is ready to be opened */
- mutex_lock(&priv->mutex);
- if (!(priv->status & STATUS_RF_KILL_MASK) &&
- (priv->status & STATUS_ASSOCIATED))
- netif_start_queue(dev);
- mutex_unlock(&priv->mutex);
+ netif_start_queue(dev);
return 0;
}
@@ -10481,13 +10474,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
spin_lock_irqsave(&priv->lock, flags);
- if (!(priv->status & STATUS_ASSOCIATED)) {
- IPW_DEBUG_INFO("Tx attempt while not associated.\n");
- priv->ieee->stats.tx_carrier_errors++;
- netif_stop_queue(dev);
- goto fail_unlock;
- }
-
#ifdef CONFIG_IPW2200_PROMISCUOUS
if (rtap_iface && netif_running(priv->prom_net_dev))
ipw_handle_promiscuous_tx(priv, txb);
@@ -10499,10 +10485,6 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
-
- fail_unlock:
- spin_unlock_irqrestore(&priv->lock, flags);
- return 1;
}
static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
@@ -10703,13 +10685,6 @@ static void ipw_link_up(struct ipw_priv *priv)
priv->last_packet_time = 0;
netif_carrier_on(priv->net_dev);
- if (netif_queue_stopped(priv->net_dev)) {
- IPW_DEBUG_NOTIF("waking queue\n");
- netif_wake_queue(priv->net_dev);
- } else {
- IPW_DEBUG_NOTIF("starting queue\n");
- netif_start_queue(priv->net_dev);
- }
cancel_delayed_work(&priv->request_scan);
cancel_delayed_work(&priv->request_direct_scan);
@@ -10739,7 +10714,6 @@ static void ipw_link_down(struct ipw_priv *priv)
{
ipw_led_link_down(priv);
netif_carrier_off(priv->net_dev);
- netif_stop_queue(priv->net_dev);
notify_wx_assoc_event(priv);
/* Cancel any queued work ... */
@@ -11419,7 +11393,6 @@ static void ipw_down(struct ipw_priv *priv)
/* Clear all bits but the RF Kill */
priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING;
netif_carrier_off(priv->net_dev);
- netif_stop_queue(priv->net_dev);
ipw_stop_nic(priv);
@@ -11522,7 +11495,6 @@ static int ipw_prom_open(struct net_device *dev)
IPW_DEBUG_INFO("prom dev->open\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
priv->sys_config.accept_all_data_frames = 1;
@@ -11558,7 +11530,6 @@ static int ipw_prom_stop(struct net_device *dev)
static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
IPW_DEBUG_INFO("prom dev->xmit\n");
- netif_stop_queue(dev);
return -EOPNOTSUPP;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 913dc9fe08f..5816230d58f 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -364,8 +364,7 @@ static void mac80211_hwsim_free(void)
struct mac80211_hwsim_data *data;
data = hwsim_radios[i]->priv;
ieee80211_unregister_hw(hwsim_radios[i]);
- if (!IS_ERR(data->dev))
- device_unregister(data->dev);
+ device_unregister(data->dev);
ieee80211_free_hw(hwsim_radios[i]);
}
}
@@ -437,7 +436,7 @@ static int __init init_mac80211_hwsim(void)
"mac80211_hwsim: device_create_drvdata "
"failed (%ld)\n", PTR_ERR(data->dev));
err = -ENOMEM;
- goto failed;
+ goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
@@ -461,7 +460,7 @@ static int __init init_mac80211_hwsim(void)
if (err < 0) {
printk(KERN_DEBUG "mac80211_hwsim: "
"ieee80211_register_hw failed (%d)\n", err);
- goto failed;
+ goto failed_hw;
}
printk(KERN_DEBUG "%s: hwaddr %s registered\n",
@@ -479,9 +478,9 @@ static int __init init_mac80211_hwsim(void)
rtnl_lock();
err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
- if (err < 0) {
+ if (err < 0)
goto failed_mon;
- }
+
err = register_netdevice(hwsim_mon);
if (err < 0)
@@ -494,7 +493,14 @@ static int __init init_mac80211_hwsim(void)
failed_mon:
rtnl_unlock();
free_netdev(hwsim_mon);
+ mac80211_hwsim_free();
+ return err;
+failed_hw:
+ device_unregister(data->dev);
+failed_drvdata:
+ ieee80211_free_hw(hw);
+ hwsim_radios[i] = 0;
failed:
mac80211_hwsim_free();
return err;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index ef671d1a3bf..902bbe78821 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -92,7 +92,7 @@ struct netfront_info {
*/
union skb_entry {
struct sk_buff *skb;
- unsigned link;
+ unsigned long link;
} tx_skbs[NET_TX_RING_SIZE];
grant_ref_t gref_tx_head;
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
@@ -125,6 +125,17 @@ struct netfront_rx_info {
struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
};
+static void skb_entry_set_link(union skb_entry *list, unsigned short id)
+{
+ list->link = id;
+}
+
+static int skb_entry_is_link(const union skb_entry *list)
+{
+ BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
+ return ((unsigned long)list->skb < PAGE_OFFSET);
+}
+
/*
* Access macros for acquiring freeing slots in tx_skbs[].
*/
@@ -132,7 +143,7 @@ struct netfront_rx_info {
static void add_id_to_freelist(unsigned *head, union skb_entry *list,
unsigned short id)
{
- list[id].link = *head;
+ skb_entry_set_link(&list[id], *head);
*head = id;
}
@@ -993,7 +1004,7 @@ static void xennet_release_tx_bufs(struct netfront_info *np)
for (i = 0; i < NET_TX_RING_SIZE; i++) {
/* Skip over entries which are actually freelist references */
- if ((unsigned long)np->tx_skbs[i].skb < PAGE_OFFSET)
+ if (skb_entry_is_link(&np->tx_skbs[i]))
continue;
skb = np->tx_skbs[i].skb;
@@ -1123,7 +1134,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
/* Initialise tx_skbs as a free chain containing every entry. */
np->tx_skb_freelist = 0;
for (i = 0; i < NET_TX_RING_SIZE; i++) {
- np->tx_skbs[i].link = i+1;
+ skb_entry_set_link(&np->tx_skbs[i], i+1);
np->grant_tx_ref[i] = GRANT_INVALID_REF;
}
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index f941f609dbf..8bf86ae2333 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -317,10 +317,8 @@ int __init dmar_table_init(void)
return -ENODEV;
}
- if (list_empty(&dmar_rmrr_units)) {
+ if (list_empty(&dmar_rmrr_units))
printk(KERN_INFO PREFIX "No RMRR found\n");
- return -ENODEV;
- }
return 0;
}
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index eecf7cbf413..5a58b075dd8 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -36,7 +36,7 @@
#define _ACPIPHP_H
#include <linux/acpi.h>
-#include <linux/kobject.h> /* for KOBJ_NAME_LEN */
+#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/pci_hotplug.h>
@@ -51,7 +51,7 @@
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
/* name size which is used for entries in pcihpfs */
-#define SLOT_NAME_SIZE KOBJ_NAME_LEN /* {_SUN} */
+#define SLOT_NAME_SIZE 20 /* {_SUN} */
struct acpiphp_bridge;
struct acpiphp_slot;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 3f7b81c065d..8d0e60ac849 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -37,7 +37,7 @@
#include "intel-iommu.h"
#include <asm/proto.h> /* force_iommu in this header in x86-64*/
#include <asm/cacheflush.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
#include "pci.h"
#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 44a46c92b72..e9c356236d2 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1040,7 +1040,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
* @dev: PCI device to handle.
* @state: PCI state from which device will issue PME#.
*/
-static bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
+bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)
{
if (!dev->pm_cap)
return false;
@@ -1123,18 +1123,10 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
}
/**
- * pci_prepare_to_sleep - prepare PCI device for system-wide transition into
- * a sleep state
- * @dev: Device to handle.
- *
- * Choose the power state appropriate for the device depending on whether
- * it can wake up the system and/or is power manageable by the platform
- * (PCI_D3hot is the default) and put the device into that state.
*/
-int pci_prepare_to_sleep(struct pci_dev *dev)
+pci_power_t pci_target_state(struct pci_dev *dev)
{
pci_power_t target_state = PCI_D3hot;
- int error;
if (platform_pci_power_manageable(dev)) {
/*
@@ -1161,7 +1153,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
* to generate PME#.
*/
if (!dev->pm_cap)
- return -EIO;
+ return PCI_POWER_ERROR;
if (dev->pme_support) {
while (target_state
@@ -1170,6 +1162,25 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
}
}
+ return target_state;
+}
+
+/**
+ * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
+ * @dev: Device to handle.
+ *
+ * Choose the power state appropriate for the device depending on whether
+ * it can wake up the system and/or is power manageable by the platform
+ * (PCI_D3hot is the default) and put the device into that state.
+ */
+int pci_prepare_to_sleep(struct pci_dev *dev)
+{
+ pci_power_t target_state = pci_target_state(dev);
+ int error;
+
+ if (target_state == PCI_POWER_ERROR)
+ return -EIO;
+
pci_enable_wake(dev, target_state, true);
error = pci_set_power_state(dev, target_state);
@@ -1181,8 +1192,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
}
/**
- * pci_back_from_sleep - turn PCI device on during system-wide transition into
- * the working state a sleep state
+ * pci_back_from_sleep - turn PCI device on during system-wide transition into working state
* @dev: Device to handle.
*
* Disable device's sytem wake-up capability and put it into D0.
@@ -1920,7 +1930,9 @@ EXPORT_SYMBOL(pci_select_bars);
EXPORT_SYMBOL(pci_set_power_state);
EXPORT_SYMBOL(pci_save_state);
EXPORT_SYMBOL(pci_restore_state);
+EXPORT_SYMBOL(pci_pme_capable);
EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL(pci_target_state);
EXPORT_SYMBOL(pci_prepare_to_sleep);
EXPORT_SYMBOL(pci_back_from_sleep);
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 4400dffbd93..e1098c302c4 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -88,7 +88,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if ((pos & 3) && cnt > 2) {
unsigned short val;
pci_user_read_config_word(dev, pos, &val);
- __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+ __put_user(cpu_to_le16(val), (__le16 __user *) buf);
buf += 2;
pos += 2;
cnt -= 2;
@@ -97,7 +97,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
while (cnt >= 4) {
unsigned int val;
pci_user_read_config_dword(dev, pos, &val);
- __put_user(cpu_to_le32(val), (unsigned int __user *) buf);
+ __put_user(cpu_to_le32(val), (__le32 __user *) buf);
buf += 4;
pos += 4;
cnt -= 4;
@@ -106,7 +106,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
if (cnt >= 2) {
unsigned short val;
pci_user_read_config_word(dev, pos, &val);
- __put_user(cpu_to_le16(val), (unsigned short __user *) buf);
+ __put_user(cpu_to_le16(val), (__le16 __user *) buf);
buf += 2;
pos += 2;
cnt -= 2;
@@ -156,8 +156,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
if ((pos & 3) && cnt > 2) {
- unsigned short val;
- __get_user(val, (unsigned short __user *) buf);
+ __le16 val;
+ __get_user(val, (__le16 __user *) buf);
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
@@ -165,8 +165,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
while (cnt >= 4) {
- unsigned int val;
- __get_user(val, (unsigned int __user *) buf);
+ __le32 val;
+ __get_user(val, (__le32 __user *) buf);
pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
buf += 4;
pos += 4;
@@ -174,8 +174,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
}
if (cnt >= 2) {
- unsigned short val;
- __get_user(val, (unsigned short __user *) buf);
+ __le16 val;
+ __get_user(val, (__le16 __user *) buf);
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index e45402adac3..e0f884034c9 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -219,7 +219,8 @@ config PCMCIA_SA1111
config PCMCIA_PXA2XX
tristate "PXA2xx support"
depends on ARM && ARCH_PXA && PCMCIA
- depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
+ depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
+ || MACH_ARMCORE || ARCH_PXA_PALM)
help
Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 85c6cc931f9..269a9e913ba 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -72,4 +72,5 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
+pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index c21f9a9c3e3..a34284b1482 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/of_platform.h>
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index f123fce65f2..bb95db7d2b7 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -5,83 +5,60 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Compulab Ltd., 2003, 2007
+ * Compulab Ltd., 2003, 2007, 2008
* Mike Rapoport <mike@compulab.co.il>
*
*/
-#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
-#include <pcmcia/ss.h>
-#include <asm/hardware.h>
#include <asm/mach-types.h>
-
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
-#include <asm/arch/cm-x270.h>
#include "soc_common.h"
+#define GPIO_PCMCIA_S0_CD_VALID (84)
+#define GPIO_PCMCIA_S0_RDYINT (82)
+#define GPIO_PCMCIA_RESET (53)
+
+#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
+#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
+
+
static struct pcmcia_irqs irqs[] = {
{ 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
- { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
};
static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
- GPIO_bit(GPIO49_nPWE) |
- GPIO_bit(GPIO50_nPIOR) |
- GPIO_bit(GPIO51_nPIOW) |
- GPIO_bit(GPIO85_nPCE_1) |
- GPIO_bit(GPIO54_nPCE_2);
-
- pxa_gpio_mode(GPIO48_nPOE_MD);
- pxa_gpio_mode(GPIO49_nPWE_MD);
- pxa_gpio_mode(GPIO50_nPIOR_MD);
- pxa_gpio_mode(GPIO51_nPIOW_MD);
- pxa_gpio_mode(GPIO85_nPCE_1_MD);
- pxa_gpio_mode(GPIO54_nPCE_2_MD);
- pxa_gpio_mode(GPIO55_nPREG_MD);
- pxa_gpio_mode(GPIO56_nPWAIT_MD);
- pxa_gpio_mode(GPIO57_nIOIS16_MD);
-
- /* Reset signal */
- pxa_gpio_mode(GPIO53_nPCE_2 | GPIO_OUT);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-
- set_irq_type(PCMCIA_S0_CD_VALID, IRQ_TYPE_EDGE_BOTH);
- set_irq_type(PCMCIA_S1_CD_VALID, IRQ_TYPE_EDGE_BOTH);
-
- /* irq's for slots: */
- set_irq_type(PCMCIA_S0_RDYINT, IRQ_TYPE_EDGE_FALLING);
- set_irq_type(PCMCIA_S1_RDYINT, IRQ_TYPE_EDGE_FALLING);
-
- skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
- return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
+ if (ret)
+ return ret;
+ gpio_direction_output(GPIO_PCMCIA_RESET, 0);
+
+ skt->irq = PCMCIA_S0_RDYINT;
+ ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+ if (!ret)
+ gpio_free(GPIO_PCMCIA_RESET);
+
+ return ret;
}
static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
{
soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
-
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQ_TYPE_NONE);
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQ_TYPE_NONE);
-
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQ_TYPE_NONE);
- set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQ_TYPE_NONE);
+ gpio_free(GPIO_PCMCIA_RESET);
}
static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
- state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0;
- state->ready = (PCC_READY(skt->nr) == 0) ? 0 : 1;
+ state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0;
+ state->ready = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1;
state->bvd1 = 1;
state->bvd2 = 1;
state->vs_3v = 0;
@@ -93,32 +70,16 @@ static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT);
-
switch (skt->nr) {
case 0:
if (state->flags & SS_RESET) {
- GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- udelay(10);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- }
- break;
- case 1:
- if (state->flags & SS_RESET) {
- GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
- GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+ gpio_set_value(GPIO_PCMCIA_RESET, 1);
udelay(10);
- GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
- GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+ gpio_set_value(GPIO_PCMCIA_RESET, 0);
}
break;
}
- pxa_gpio_mode(GPIO49_nPWE_MD);
-
return 0;
}
@@ -139,7 +100,7 @@ static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
.configure_socket = cmx270_pcmcia_configure_socket,
.socket_init = cmx270_pcmcia_socket_init,
.socket_suspend = cmx270_pcmcia_socket_suspend,
- .nr = 2,
+ .nr = 1,
};
static struct platform_device *cmx270_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
new file mode 100644
index 00000000000..4abde190c1f
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -0,0 +1,118 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_palmtx.c
+ *
+ * Driver for Palm T|X PCMCIA
+ *
+ * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/palmtx.h>
+
+#include "soc_common.h"
+
+static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ skt->irq = IRQ_GPIO(GPIO_NR_PALMTX_PCMCIA_READY);
+ return 0;
+}
+
+static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->detect = 1; /* always inserted */
+ state->ready = !!gpio_get_value(GPIO_NR_PALMTX_PCMCIA_READY);
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->wrprot = 0;
+ state->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int
+palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER1, 1);
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER2, 1);
+ gpio_set_value(GPIO_NR_PALMTX_PCMCIA_RESET,
+ !!(state->flags & SS_RESET));
+
+ return 0;
+}
+
+static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level palmtx_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .first = 0,
+ .nr = 1,
+
+ .hw_init = palmtx_pcmcia_hw_init,
+ .hw_shutdown = palmtx_pcmcia_hw_shutdown,
+
+ .socket_state = palmtx_pcmcia_socket_state,
+ .configure_socket = palmtx_pcmcia_configure_socket,
+
+ .socket_init = palmtx_pcmcia_socket_init,
+ .socket_suspend = palmtx_pcmcia_socket_suspend,
+};
+
+static struct platform_device *palmtx_pcmcia_device;
+
+static int __init palmtx_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_palmtx())
+ return -ENODEV;
+
+ palmtx_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!palmtx_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(palmtx_pcmcia_device, &palmtx_pcmcia_ops,
+ sizeof(palmtx_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(palmtx_pcmcia_device);
+
+ if (ret)
+ platform_device_put(palmtx_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit palmtx_pcmcia_exit(void)
+{
+ platform_device_unregister(palmtx_pcmcia_device);
+}
+
+fs_initcall(palmtx_pcmcia_init);
+module_exit(palmtx_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Palm T|X");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 58c806e9c58..4d17d384578 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -49,4 +49,10 @@ config BATTERY_OLPC
help
Say Y to enable support for the battery on the OLPC laptop.
+config BATTERY_PALMTX
+ tristate "Palm T|X battery"
+ depends on MACH_PALMTX
+ help
+ Say Y to enable support for the battery in Palm T|X.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6413ded5fe5..6f43a54ee42 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_APM_POWER) += apm_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
+obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index a4892275659..936bae560fa 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -78,7 +78,7 @@ static void find_main_battery(void)
main_battery = NULL;
bp.main = main_battery;
- error = class_for_each_device(power_supply_class, &bp,
+ error = class_for_each_device(power_supply_class, NULL, &bp,
__find_main_battery);
if (error) {
main_battery = bp.main;
diff --git a/drivers/power/palmtx_battery.c b/drivers/power/palmtx_battery.c
new file mode 100644
index 00000000000..244bb273a63
--- /dev/null
+++ b/drivers/power/palmtx_battery.c
@@ -0,0 +1,198 @@
+/*
+ * linux/drivers/power/palmtx_battery.c
+ *
+ * Battery measurement code for Palm T|X Handheld computer
+ *
+ * based on tosa_battery.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/wm97xx.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/palmtx.h>
+
+static DEFINE_MUTEX(bat_lock);
+static struct work_struct bat_work;
+struct mutex work_lock;
+int bat_status = POWER_SUPPLY_STATUS_DISCHARGING;
+
+static unsigned long palmtx_read_bat(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ WM97XX_AUX_ID3) * 1000 / 414;
+}
+
+static unsigned long palmtx_read_temp(struct power_supply *bat_ps)
+{
+ return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+ WM97XX_AUX_ID2);
+}
+
+static int palmtx_bat_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = bat_status;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = palmtx_read_bat(bat_ps);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = PALMTX_BAT_MAX_VOLTAGE;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = PALMTX_BAT_MIN_VOLTAGE;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = palmtx_read_temp(bat_ps);
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void palmtx_bat_external_power_changed(struct power_supply *bat_ps)
+{
+ schedule_work(&bat_work);
+}
+
+static char *status_text[] = {
+ [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown",
+ [POWER_SUPPLY_STATUS_CHARGING] = "Charging",
+ [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging",
+};
+
+static void palmtx_bat_update(struct power_supply *bat_ps)
+{
+ int old_status = bat_status;
+
+ mutex_lock(&work_lock);
+
+ bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ?
+ POWER_SUPPLY_STATUS_CHARGING :
+ POWER_SUPPLY_STATUS_DISCHARGING;
+
+ if (old_status != bat_status) {
+ pr_debug("%s %s -> %s\n", bat_ps->name,
+ status_text[old_status],
+ status_text[bat_status]);
+ power_supply_changed(bat_ps);
+ }
+
+ mutex_unlock(&work_lock);
+}
+
+static enum power_supply_property palmtx_bat_main_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_PRESENT,
+};
+
+struct power_supply bat_ps = {
+ .name = "main-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = palmtx_bat_main_props,
+ .num_properties = ARRAY_SIZE(palmtx_bat_main_props),
+ .get_property = palmtx_bat_get_property,
+ .external_power_changed = palmtx_bat_external_power_changed,
+ .use_for_apm = 1,
+};
+
+static void palmtx_bat_work(struct work_struct *work)
+{
+ palmtx_bat_update(&bat_ps);
+}
+
+#ifdef CONFIG_PM
+static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state)
+{
+ flush_scheduled_work();
+ return 0;
+}
+
+static int palmtx_bat_resume(struct platform_device *dev)
+{
+ schedule_work(&bat_work);
+ return 0;
+}
+#else
+#define palmtx_bat_suspend NULL
+#define palmtx_bat_resume NULL
+#endif
+
+static int __devinit palmtx_bat_probe(struct platform_device *dev)
+{
+ int ret = 0;
+
+ if (!machine_is_palmtx())
+ return -ENODEV;
+
+ mutex_init(&work_lock);
+
+ INIT_WORK(&bat_work, palmtx_bat_work);
+
+ ret = power_supply_register(&dev->dev, &bat_ps);
+ if (!ret)
+ schedule_work(&bat_work);
+
+ return ret;
+}
+
+static int __devexit palmtx_bat_remove(struct platform_device *dev)
+{
+ power_supply_unregister(&bat_ps);
+ return 0;
+}
+
+static struct platform_driver palmtx_bat_driver = {
+ .driver.name = "wm97xx-battery",
+ .driver.owner = THIS_MODULE,
+ .probe = palmtx_bat_probe,
+ .remove = __devexit_p(palmtx_bat_remove),
+ .suspend = palmtx_bat_suspend,
+ .resume = palmtx_bat_resume,
+};
+
+static int __init palmtx_bat_init(void)
+{
+ return platform_driver_register(&palmtx_bat_driver);
+}
+
+static void __exit palmtx_bat_exit(void)
+{
+ platform_driver_unregister(&palmtx_bat_driver);
+}
+
+module_init(palmtx_bat_init);
+module_exit(palmtx_bat_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("Palm T|X battery driver");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index af1633eb3b7..cb1ccb47292 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -41,7 +41,7 @@ static void power_supply_changed_work(struct work_struct *work)
dev_dbg(psy->dev, "%s\n", __func__);
- class_for_each_device(power_supply_class, psy,
+ class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);
power_supply_update_leds(psy);
@@ -79,7 +79,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
{
int error;
- error = class_for_each_device(power_supply_class, psy,
+ error = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_am_i_supplied);
dev_dbg(psy->dev, "%s %d\n", __func__, error);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index fc85bf2e4a9..90ab7382540 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -273,6 +273,25 @@ comment "SPI RTC drivers"
if SPI_MASTER
+config RTC_DRV_M41T94
+ tristate "ST M41T94"
+ help
+ If you say yes here you will get support for the
+ ST M41T94 SPI RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-m41t94.
+
+config RTC_DRV_DS1305
+ tristate "Dallas/Maxim DS1305/DS1306"
+ help
+ Select this driver to get support for the Dallas/Maxim DS1305
+ and DS1306 real time clock chips. These support a trickle
+ charger, alarms, and NVRAM in addition to the clock.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1305.
+
config RTC_DRV_MAX6902
tristate "Maxim MAX6902"
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b5d9d67df88..18622ef84ca 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
+obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
+obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 58b7336640f..d397fa5f3a9 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -345,7 +345,7 @@ struct rtc_device *rtc_class_open(char *name)
struct device *dev;
struct rtc_device *rtc = NULL;
- dev = class_find_device(rtc_class, name, __rtc_match);
+ dev = class_find_device(rtc_class, NULL, name, __rtc_match);
if (dev)
rtc = to_rtc_device(dev);
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 9c3db934cc2..cd32d05db77 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -171,8 +171,10 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
| BIN2BCD(tm.tm_mday) << 24
| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
- if (alrm->enabled)
+ if (alrm->enabled) {
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+ }
pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
@@ -191,28 +193,22 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
+ /* important: scrub old status before enabling IRQs */
switch (cmd) {
case RTC_AIE_OFF: /* alarm off */
at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
break;
case RTC_AIE_ON: /* alarm on */
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
break;
case RTC_UIE_OFF: /* update off */
- case RTC_PIE_OFF: /* periodic off */
at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
break;
case RTC_UIE_ON: /* update on */
- case RTC_PIE_ON: /* periodic on */
+ at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
break;
- case RTC_IRQP_READ: /* read periodic alarm frequency */
- ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
- break;
- case RTC_IRQP_SET: /* set periodic alarm frequency */
- if (arg != AT91_RTC_FREQ)
- ret = -EINVAL;
- break;
default:
ret = -ENOIOCTLCMD;
break;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index d7bb9bac71d..6ea349aba3b 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -36,25 +36,9 @@
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
-#ifdef CONFIG_HPET_EMULATE_RTC
-#include <asm/hpet.h>
-#endif
-
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
-#ifndef CONFIG_HPET_EMULATE_RTC
-#define is_hpet_enabled() 0
-#define hpet_set_alarm_time(hrs, min, sec) do { } while (0)
-#define hpet_set_periodic_freq(arg) 0
-#define hpet_mask_rtc_irq_bit(arg) do { } while (0)
-#define hpet_set_rtc_irq_bit(arg) do { } while (0)
-#define hpet_rtc_timer_init() do { } while (0)
-#define hpet_register_irq_handler(h) 0
-#define hpet_unregister_irq_handler(h) do { } while (0)
-extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
-#endif
-
struct cmos_rtc {
struct rtc_device *rtc;
struct device *dev;
@@ -93,6 +77,72 @@ static inline int is_intr(u8 rtc_intr)
/*----------------------------------------------------------------*/
+/* Much modern x86 hardware has HPETs (10+ MHz timers) which, because
+ * many BIOS programmers don't set up "sane mode" IRQ routing, are mostly
+ * used in a broken "legacy replacement" mode. The breakage includes
+ * HPET #1 hijacking the IRQ for this RTC, and being unavailable for
+ * other (better) use.
+ *
+ * When that broken mode is in use, platform glue provides a partial
+ * emulation of hardware RTC IRQ facilities using HPET #1. We don't
+ * want to use HPET for anything except those IRQs though...
+ */
+#ifdef CONFIG_HPET_EMULATE_RTC
+#include <asm/hpet.h>
+#else
+
+static inline int is_hpet_enabled(void)
+{
+ return 0;
+}
+
+static inline int hpet_mask_rtc_irq_bit(unsigned long mask)
+{
+ return 0;
+}
+
+static inline int hpet_set_rtc_irq_bit(unsigned long mask)
+{
+ return 0;
+}
+
+static inline int
+hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
+{
+ return 0;
+}
+
+static inline int hpet_set_periodic_freq(unsigned long freq)
+{
+ return 0;
+}
+
+static inline int hpet_rtc_dropped_irq(void)
+{
+ return 0;
+}
+
+static inline int hpet_rtc_timer_init(void)
+{
+ return 0;
+}
+
+extern irq_handler_t hpet_rtc_interrupt;
+
+static inline int hpet_register_irq_handler(irq_handler_t handler)
+{
+ return 0;
+}
+
+static inline int hpet_unregister_irq_handler(irq_handler_t handler)
+{
+ return 0;
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
@@ -185,11 +235,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return 0;
}
+static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
+{
+ unsigned char rtc_intr;
+
+ /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
+ * allegedly some older rtcs need that to handle irqs properly
+ */
+ rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+
+ if (is_hpet_enabled())
+ return;
+
+ rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+ if (is_intr(rtc_intr))
+ rtc_update_irq(cmos->rtc, 1, rtc_intr);
+}
+
+static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
+{
+ unsigned char rtc_control;
+
+ /* flush any pending IRQ status, notably for update irqs,
+ * before we enable new IRQs
+ */
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ cmos_checkintr(cmos, rtc_control);
+
+ rtc_control |= mask;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_set_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, rtc_control);
+}
+
+static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
+{
+ unsigned char rtc_control;
+
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ rtc_control &= ~mask;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_mask_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, rtc_control);
+}
+
static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
unsigned char mon, mday, hrs, min, sec;
- unsigned char rtc_control, rtc_intr;
if (!is_valid_irq(cmos->irq))
return -EIO;
@@ -213,17 +308,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
sec = t->time.tm_sec;
sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
- hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
spin_lock_irq(&rtc_lock);
/* next rtc irq must not be from previous alarm setting */
- rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
+ cmos_irq_disable(cmos, RTC_AIE);
/* update alarm */
CMOS_WRITE(hrs, RTC_HOURS_ALARM);
@@ -237,14 +325,13 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
CMOS_WRITE(mon, cmos->mon_alrm);
}
- if (t->enabled) {
- rtc_control |= RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
- }
+ /* FIXME the HPET alarm glue currently ignores day_alrm
+ * and mon_alrm ...
+ */
+ hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
+
+ if (t->enabled)
+ cmos_irq_enable(cmos, RTC_AIE);
spin_unlock_irq(&rtc_lock);
@@ -267,8 +354,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
f = 16 - f;
spin_lock_irqsave(&rtc_lock, flags);
- if (!hpet_set_periodic_freq(freq))
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
+ hpet_set_periodic_freq(freq);
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -277,26 +364,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
static int cmos_irq_set_state(struct device *dev, int enabled)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- unsigned char rtc_control, rtc_intr;
unsigned long flags;
if (!is_valid_irq(cmos->irq))
return -ENXIO;
spin_lock_irqsave(&rtc_lock, flags);
- rtc_control = CMOS_READ(RTC_CONTROL);
if (enabled)
- rtc_control |= RTC_PIE;
+ cmos_irq_enable(cmos, RTC_PIE);
else
- rtc_control &= ~RTC_PIE;
-
- CMOS_WRITE(rtc_control, RTC_CONTROL);
-
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
+ cmos_irq_disable(cmos, RTC_PIE);
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
@@ -308,7 +386,6 @@ static int
cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- unsigned char rtc_control, rtc_intr;
unsigned long flags;
switch (cmd) {
@@ -316,51 +393,29 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
case RTC_AIE_ON:
case RTC_UIE_OFF:
case RTC_UIE_ON:
- case RTC_PIE_OFF:
- case RTC_PIE_ON:
if (!is_valid_irq(cmos->irq))
return -EINVAL;
break;
+ /* PIE ON/OFF is handled by cmos_irq_set_state() */
default:
return -ENOIOCTLCMD;
}
spin_lock_irqsave(&rtc_lock, flags);
- rtc_control = CMOS_READ(RTC_CONTROL);
switch (cmd) {
case RTC_AIE_OFF: /* alarm off */
- rtc_control &= ~RTC_AIE;
- hpet_mask_rtc_irq_bit(RTC_AIE);
+ cmos_irq_disable(cmos, RTC_AIE);
break;
case RTC_AIE_ON: /* alarm on */
- rtc_control |= RTC_AIE;
- hpet_set_rtc_irq_bit(RTC_AIE);
+ cmos_irq_enable(cmos, RTC_AIE);
break;
case RTC_UIE_OFF: /* update off */
- rtc_control &= ~RTC_UIE;
- hpet_mask_rtc_irq_bit(RTC_UIE);
+ cmos_irq_disable(cmos, RTC_UIE);
break;
case RTC_UIE_ON: /* update on */
- rtc_control |= RTC_UIE;
- hpet_set_rtc_irq_bit(RTC_UIE);
- break;
- case RTC_PIE_OFF: /* periodic off */
- rtc_control &= ~RTC_PIE;
- hpet_mask_rtc_irq_bit(RTC_PIE);
- break;
- case RTC_PIE_ON: /* periodic on */
- rtc_control |= RTC_PIE;
- hpet_set_rtc_irq_bit(RTC_PIE);
+ cmos_irq_enable(cmos, RTC_UIE);
break;
}
- if (!is_hpet_enabled())
- CMOS_WRITE(rtc_control, RTC_CONTROL);
-
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(rtc_intr))
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
-
spin_unlock_irqrestore(&rtc_lock, flags);
return 0;
}
@@ -502,27 +557,29 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
u8 rtc_control;
spin_lock(&rtc_lock);
- /*
- * In this case it is HPET RTC interrupt handler
- * calling us, with the interrupt information
- * passed as arg1, instead of irq.
+
+ /* When the HPET interrupt handler calls us, the interrupt
+ * status is passed as arg1 instead of the irq number. But
+ * always clear irq status, even when HPET is in the way.
+ *
+ * Note that HPET and RTC are almost certainly out of phase,
+ * giving different IRQ status ...
*/
+ irqstat = CMOS_READ(RTC_INTR_FLAGS);
+ rtc_control = CMOS_READ(RTC_CONTROL);
if (is_hpet_enabled())
irqstat = (unsigned long)irq & 0xF0;
- else {
- irqstat = CMOS_READ(RTC_INTR_FLAGS);
- rtc_control = CMOS_READ(RTC_CONTROL);
- irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
- }
+ irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
/* All Linux RTC alarms should be treated as if they were oneshot.
* Similar code may be needed in system wakeup paths, in case the
* alarm woke the system.
*/
if (irqstat & RTC_AIE) {
- rtc_control = CMOS_READ(RTC_CONTROL);
rtc_control &= ~RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
+ hpet_mask_rtc_irq_bit(RTC_AIE);
+
CMOS_READ(RTC_INTR_FLAGS);
}
spin_unlock(&rtc_lock);
@@ -629,18 +686,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
* do something about other clock frequencies.
*/
cmos_rtc.rtc->irq_freq = 1024;
- if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq))
- CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+ hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
+
+ /* disable irqs */
+ cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
- /* disable irqs.
- *
- * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
- * allegedly some older rtcs need that to handle irqs properly
- */
rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
spin_unlock_irq(&rtc_lock);
@@ -687,7 +739,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup2;
}
- pr_info("%s: alarms up to one %s%s\n",
+ pr_info("%s: alarms up to one %s%s%s\n",
cmos_rtc.rtc->dev.bus_id,
is_valid_irq(rtc_irq)
? (cmos_rtc.mon_alrm
@@ -695,8 +747,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
: (cmos_rtc.day_alrm
? "month" : "day"))
: "no",
- cmos_rtc.century ? ", y3k" : ""
- );
+ cmos_rtc.century ? ", y3k" : "",
+ is_hpet_enabled() ? ", hpet irqs" : "");
return 0;
@@ -713,13 +765,8 @@ cleanup0:
static void cmos_do_shutdown(void)
{
- unsigned char rtc_control;
-
spin_lock_irq(&rtc_lock);
- rtc_control = CMOS_READ(RTC_CONTROL);
- rtc_control &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
+ cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
spin_unlock_irq(&rtc_lock);
}
@@ -760,17 +807,17 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
spin_lock_irq(&rtc_lock);
cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
- unsigned char irqstat;
+ unsigned char mask;
if (do_wake)
- tmp &= ~(RTC_PIE|RTC_UIE);
+ mask = RTC_IRQMASK & ~RTC_AIE;
else
- tmp &= ~(RTC_PIE|RTC_AIE|RTC_UIE);
+ mask = RTC_IRQMASK;
+ tmp &= ~mask;
CMOS_WRITE(tmp, RTC_CONTROL);
- irqstat = CMOS_READ(RTC_INTR_FLAGS);
- irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(irqstat))
- rtc_update_irq(cmos->rtc, 1, irqstat);
+ hpet_mask_rtc_irq_bit(mask);
+
+ cmos_checkintr(cmos, tmp);
}
spin_unlock_irq(&rtc_lock);
@@ -796,7 +843,8 @@ static int cmos_resume(struct device *dev)
unsigned char tmp = cmos->suspend_ctrl;
/* re-enable any irqs previously active */
- if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
+ if (tmp & RTC_IRQMASK) {
+ unsigned char mask;
if (cmos->enabled_wake) {
if (cmos->wake_off)
@@ -807,18 +855,28 @@ static int cmos_resume(struct device *dev)
}
spin_lock_irq(&rtc_lock);
- CMOS_WRITE(tmp, RTC_CONTROL);
- tmp = CMOS_READ(RTC_INTR_FLAGS);
- tmp &= (cmos->suspend_ctrl & RTC_IRQMASK) | RTC_IRQF;
- if (is_intr(tmp))
- rtc_update_irq(cmos->rtc, 1, tmp);
+ do {
+ CMOS_WRITE(tmp, RTC_CONTROL);
+ hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
+
+ mask = CMOS_READ(RTC_INTR_FLAGS);
+ mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
+ if (!is_hpet_enabled() || !is_intr(mask))
+ break;
+
+ /* force one-shot behavior if HPET blocked
+ * the wake alarm's irq
+ */
+ rtc_update_irq(cmos->rtc, 1, mask);
+ tmp &= ~RTC_AIE;
+ hpet_mask_rtc_irq_bit(RTC_AIE);
+ } while (mask & RTC_AIE);
spin_unlock_irq(&rtc_lock);
}
pr_debug("%s: resume, ctrl %02x\n",
cmos_rtc.rtc->dev.bus_id,
- cmos->suspend_ctrl);
-
+ tmp);
return 0;
}
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 0114a78b7cb..0a870b7e5c3 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -209,7 +209,7 @@ static unsigned int rtc_dev_poll(struct file *file, poll_table *wait)
return (data != 0) ? (POLLIN | POLLRDNORM) : 0;
}
-static int rtc_dev_ioctl(struct inode *inode, struct file *file,
+static long rtc_dev_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int err = 0;
@@ -219,6 +219,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
struct rtc_wkalrm alarm;
void __user *uarg = (void __user *) arg;
+ err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return -EBUSY;
+
/* check that the calling task has appropriate permissions
* for certain ioctls. doing this check here is useful
* to avoid duplicate code in each driver.
@@ -227,26 +231,31 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
case RTC_EPOCH_SET:
case RTC_SET_TIME:
if (!capable(CAP_SYS_TIME))
- return -EACCES;
+ err = -EACCES;
break;
case RTC_IRQP_SET:
if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
- return -EACCES;
+ err = -EACCES;
break;
case RTC_PIE_ON:
if (rtc->irq_freq > rtc->max_user_freq &&
!capable(CAP_SYS_RESOURCE))
- return -EACCES;
+ err = -EACCES;
break;
}
+ if (err)
+ goto done;
+
/* try the driver's ioctl interface */
if (ops->ioctl) {
err = ops->ioctl(rtc->dev.parent, cmd, arg);
- if (err != -ENOIOCTLCMD)
+ if (err != -ENOIOCTLCMD) {
+ mutex_unlock(&rtc->ops_lock);
return err;
+ }
}
/* if the driver does not provide the ioctl interface
@@ -265,15 +274,19 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case RTC_ALM_READ:
+ mutex_unlock(&rtc->ops_lock);
+
err = rtc_read_alarm(rtc, &alarm);
if (err < 0)
return err;
if (copy_to_user(uarg, &alarm.time, sizeof(tm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
case RTC_ALM_SET:
+ mutex_unlock(&rtc->ops_lock);
+
if (copy_from_user(&alarm.time, uarg, sizeof(tm)))
return -EFAULT;
@@ -321,24 +334,26 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
}
}
- err = rtc_set_alarm(rtc, &alarm);
- break;
+ return rtc_set_alarm(rtc, &alarm);
case RTC_RD_TIME:
+ mutex_unlock(&rtc->ops_lock);
+
err = rtc_read_time(rtc, &tm);
if (err < 0)
return err;
if (copy_to_user(uarg, &tm, sizeof(tm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
case RTC_SET_TIME:
+ mutex_unlock(&rtc->ops_lock);
+
if (copy_from_user(&tm, uarg, sizeof(tm)))
return -EFAULT;
- err = rtc_set_time(rtc, &tm);
- break;
+ return rtc_set_time(rtc, &tm);
case RTC_PIE_ON:
err = rtc_irq_set_state(rtc, NULL, 1);
@@ -376,34 +391,37 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
break;
#endif
case RTC_WKALM_SET:
+ mutex_unlock(&rtc->ops_lock);
if (copy_from_user(&alarm, uarg, sizeof(alarm)))
return -EFAULT;
- err = rtc_set_alarm(rtc, &alarm);
- break;
+ return rtc_set_alarm(rtc, &alarm);
case RTC_WKALM_RD:
+ mutex_unlock(&rtc->ops_lock);
err = rtc_read_alarm(rtc, &alarm);
if (err < 0)
return err;
if (copy_to_user(uarg, &alarm, sizeof(alarm)))
- return -EFAULT;
- break;
+ err = -EFAULT;
+ return err;
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
case RTC_UIE_OFF:
clear_uie(rtc);
- return 0;
+ break;
case RTC_UIE_ON:
- return set_uie(rtc);
+ err = set_uie(rtc);
#endif
default:
err = -ENOTTY;
break;
}
+done:
+ mutex_unlock(&rtc->ops_lock);
return err;
}
@@ -432,7 +450,7 @@ static const struct file_operations rtc_dev_fops = {
.llseek = no_llseek,
.read = rtc_dev_read,
.poll = rtc_dev_poll,
- .ioctl = rtc_dev_ioctl,
+ .unlocked_ioctl = rtc_dev_ioctl,
.open = rtc_dev_open,
.release = rtc_dev_release,
.fasync = rtc_dev_fasync,
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
new file mode 100644
index 00000000000..b91d02a3ace
--- /dev/null
+++ b/drivers/rtc/rtc-ds1305.c
@@ -0,0 +1,847 @@
+/*
+ * rtc-ds1305.c -- driver for DS1305 and DS1306 SPI RTC chips
+ *
+ * Copyright (C) 2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ds1305.h>
+
+
+/*
+ * Registers ... mask DS1305_WRITE into register address to write,
+ * otherwise you're reading it. All non-bitmask values are BCD.
+ */
+#define DS1305_WRITE 0x80
+
+
+/* RTC date/time ... the main special cases are that we:
+ * - Need fancy "hours" encoding in 12hour mode
+ * - Don't rely on the "day-of-week" field (or tm_wday)
+ * - Are a 21st-century clock (2000 <= year < 2100)
+ */
+#define DS1305_RTC_LEN 7 /* bytes for RTC regs */
+
+#define DS1305_SEC 0x00 /* register addresses */
+#define DS1305_MIN 0x01
+#define DS1305_HOUR 0x02
+# define DS1305_HR_12 0x40 /* set == 12 hr mode */
+# define DS1305_HR_PM 0x20 /* set == PM (12hr mode) */
+#define DS1305_WDAY 0x03
+#define DS1305_MDAY 0x04
+#define DS1305_MON 0x05
+#define DS1305_YEAR 0x06
+
+
+/* The two alarms have only sec/min/hour/wday fields (ALM_LEN).
+ * DS1305_ALM_DISABLE disables a match field (some combos are bad).
+ *
+ * NOTE that since we don't use WDAY, we limit ourselves to alarms
+ * only one day into the future (vs potentially up to a week).
+ *
+ * NOTE ALSO that while we could generate once-a-second IRQs (UIE), we
+ * don't currently support them. We'd either need to do it only when
+ * no alarm is pending (not the standard model), or to use the second
+ * alarm (implying that this is a DS1305 not DS1306, *and* that either
+ * it's wired up a second IRQ we know, or that INTCN is set)
+ */
+#define DS1305_ALM_LEN 4 /* bytes for ALM regs */
+#define DS1305_ALM_DISABLE 0x80
+
+#define DS1305_ALM0(r) (0x07 + (r)) /* register addresses */
+#define DS1305_ALM1(r) (0x0b + (r))
+
+
+/* three control registers */
+#define DS1305_CONTROL_LEN 3 /* bytes of control regs */
+
+#define DS1305_CONTROL 0x0f /* register addresses */
+# define DS1305_nEOSC 0x80 /* low enables oscillator */
+# define DS1305_WP 0x40 /* write protect */
+# define DS1305_INTCN 0x04 /* clear == only int0 used */
+# define DS1306_1HZ 0x04 /* enable 1Hz output */
+# define DS1305_AEI1 0x02 /* enable ALM1 IRQ */
+# define DS1305_AEI0 0x01 /* enable ALM0 IRQ */
+#define DS1305_STATUS 0x10
+/* status has just AEIx bits, mirrored as IRQFx */
+#define DS1305_TRICKLE 0x11
+/* trickle bits are defined in <linux/spi/ds1305.h> */
+
+/* a bunch of NVRAM */
+#define DS1305_NVRAM_LEN 96 /* bytes of NVRAM */
+
+#define DS1305_NVRAM 0x20 /* register addresses */
+
+
+struct ds1305 {
+ struct spi_device *spi;
+ struct rtc_device *rtc;
+
+ struct work_struct work;
+
+ unsigned long flags;
+#define FLAG_EXITING 0
+
+ bool hr12;
+ u8 ctrl[DS1305_CONTROL_LEN];
+};
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Utilities ... tolerate 12-hour AM/PM notation in case of non-Linux
+ * software (like a bootloader) which may require it.
+ */
+
+static unsigned bcd2hour(u8 bcd)
+{
+ if (bcd & DS1305_HR_12) {
+ unsigned hour = 0;
+
+ bcd &= ~DS1305_HR_12;
+ if (bcd & DS1305_HR_PM) {
+ hour = 12;
+ bcd &= ~DS1305_HR_PM;
+ }
+ hour += BCD2BIN(bcd);
+ return hour - 1;
+ }
+ return BCD2BIN(bcd);
+}
+
+static u8 hour2bcd(bool hr12, int hour)
+{
+ if (hr12) {
+ hour++;
+ if (hour <= 12)
+ return DS1305_HR_12 | BIN2BCD(hour);
+ hour -= 12;
+ return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour);
+ }
+ return BIN2BCD(hour);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to RTC framework
+ */
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 buf[2];
+ int status = -ENOIOCTLCMD;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ status = 0;
+ if (!(buf[1] & DS1305_AEI0))
+ goto done;
+ buf[1] &= ~DS1305_AEI0;
+ break;
+
+ case RTC_AIE_ON:
+ status = 0;
+ if (ds1305->ctrl[0] & DS1305_AEI0)
+ goto done;
+ buf[1] |= DS1305_AEI0;
+ break;
+ }
+ if (status == 0) {
+ status = spi_write_then_read(ds1305->spi, buf, sizeof buf,
+ NULL, 0);
+ if (status >= 0)
+ ds1305->ctrl[0] = buf[1];
+ }
+
+done:
+ return status;
+}
+
+#else
+#define ds1305_ioctl NULL
+#endif
+
+/*
+ * Get/set of date and time is pretty normal.
+ */
+
+static int ds1305_get_time(struct device *dev, struct rtc_time *time)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 addr = DS1305_SEC;
+ u8 buf[DS1305_RTC_LEN];
+ int status;
+
+ /* Use write-then-read to get all the date/time registers
+ * since dma from stack is nonportable
+ */
+ status = spi_write_then_read(ds1305->spi, &addr, sizeof addr,
+ buf, sizeof buf);
+ if (status < 0)
+ return status;
+
+ dev_vdbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+ "read", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6]);
+
+ /* Decode the registers */
+ time->tm_sec = BCD2BIN(buf[DS1305_SEC]);
+ time->tm_min = BCD2BIN(buf[DS1305_MIN]);
+ time->tm_hour = bcd2hour(buf[DS1305_HOUR]);
+ time->tm_wday = buf[DS1305_WDAY] - 1;
+ time->tm_mday = BCD2BIN(buf[DS1305_MDAY]);
+ time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1;
+ time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100;
+
+ dev_vdbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "read", time->tm_sec, time->tm_min,
+ time->tm_hour, time->tm_mday,
+ time->tm_mon, time->tm_year, time->tm_wday);
+
+ /* Time may not be set */
+ return rtc_valid_tm(time);
+}
+
+static int ds1305_set_time(struct device *dev, struct rtc_time *time)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ u8 buf[1 + DS1305_RTC_LEN];
+ u8 *bp = buf;
+
+ dev_vdbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "write", time->tm_sec, time->tm_min,
+ time->tm_hour, time->tm_mday,
+ time->tm_mon, time->tm_year, time->tm_wday);
+
+ /* Write registers starting at the first time/date address. */
+ *bp++ = DS1305_WRITE | DS1305_SEC;
+
+ *bp++ = BIN2BCD(time->tm_sec);
+ *bp++ = BIN2BCD(time->tm_min);
+ *bp++ = hour2bcd(ds1305->hr12, time->tm_hour);
+ *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1;
+ *bp++ = BIN2BCD(time->tm_mday);
+ *bp++ = BIN2BCD(time->tm_mon + 1);
+ *bp++ = BIN2BCD(time->tm_year - 100);
+
+ dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
+ "write", buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ /* use write-then-read since dma from stack is nonportable */
+ return spi_write_then_read(ds1305->spi, buf, sizeof buf,
+ NULL, 0);
+}
+
+/*
+ * Get/set of alarm is a bit funky:
+ *
+ * - First there's the inherent raciness of getting the (partitioned)
+ * status of an alarm that could trigger while we're reading parts
+ * of that status.
+ *
+ * - Second there's its limited range (we could increase it a bit by
+ * relying on WDAY), which means it will easily roll over.
+ *
+ * - Third there's the choice of two alarms and alarm signals.
+ * Here we use ALM0 and expect that nINT0 (open drain) is used;
+ * that's the only real option for DS1306 runtime alarms, and is
+ * natural on DS1305.
+ *
+ * - Fourth, there's also ALM1, and a second interrupt signal:
+ * + On DS1305 ALM1 uses nINT1 (when INTCN=1) else nINT0;
+ * + On DS1306 ALM1 only uses INT1 (an active high pulse)
+ * and it won't work when VCC1 is active.
+ *
+ * So to be most general, we should probably set both alarms to the
+ * same value, letting ALM1 be the wakeup event source on DS1306
+ * and handling several wiring options on DS1305.
+ *
+ * - Fifth, we support the polled mode (as well as possible; why not?)
+ * even when no interrupt line is wired to an IRQ.
+ */
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ struct spi_device *spi = ds1305->spi;
+ u8 addr;
+ int status;
+ u8 buf[DS1305_ALM_LEN];
+
+ /* Refresh control register cache BEFORE reading ALM0 registers,
+ * since reading alarm registers acks any pending IRQ. That
+ * makes returning "pending" status a bit of a lie, but that bit
+ * of EFI status is at best fragile anyway (given IRQ handlers).
+ */
+ addr = DS1305_CONTROL;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ ds1305->ctrl, sizeof ds1305->ctrl);
+ if (status < 0)
+ return status;
+
+ alm->enabled = !!(ds1305->ctrl[0] & DS1305_AEI0);
+ alm->pending = !!(ds1305->ctrl[1] & DS1305_AEI0);
+
+ /* get and check ALM0 registers */
+ addr = DS1305_ALM0(DS1305_SEC);
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ buf, sizeof buf);
+ if (status < 0)
+ return status;
+
+ dev_vdbg(dev, "%s: %02x %02x %02x %02x\n",
+ "alm0 read", buf[DS1305_SEC], buf[DS1305_MIN],
+ buf[DS1305_HOUR], buf[DS1305_WDAY]);
+
+ if ((DS1305_ALM_DISABLE & buf[DS1305_SEC])
+ || (DS1305_ALM_DISABLE & buf[DS1305_MIN])
+ || (DS1305_ALM_DISABLE & buf[DS1305_HOUR]))
+ return -EIO;
+
+ /* Stuff these values into alm->time and let RTC framework code
+ * fill in the rest ... and also handle rollover to tomorrow when
+ * that's needed.
+ */
+ alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]);
+ alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]);
+ alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
+ alm->time.tm_mday = -1;
+ alm->time.tm_mon = -1;
+ alm->time.tm_year = -1;
+ /* next three fields are unused by Linux */
+ alm->time.tm_wday = -1;
+ alm->time.tm_mday = -1;
+ alm->time.tm_isdst = -1;
+
+ return 0;
+}
+
+/*
+ * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl)
+ */
+static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ struct spi_device *spi = ds1305->spi;
+ unsigned long now, later;
+ struct rtc_time tm;
+ int status;
+ u8 buf[1 + DS1305_ALM_LEN];
+
+ /* convert desired alarm to time_t */
+ status = rtc_tm_to_time(&alm->time, &later);
+ if (status < 0)
+ return status;
+
+ /* Read current time as time_t */
+ status = ds1305_get_time(dev, &tm);
+ if (status < 0)
+ return status;
+ status = rtc_tm_to_time(&tm, &now);
+ if (status < 0)
+ return status;
+
+ /* make sure alarm fires within the next 24 hours */
+ if (later <= now)
+ return -EINVAL;
+ if ((later - now) > 24 * 60 * 60)
+ return -EDOM;
+
+ /* disable alarm if needed */
+ if (ds1305->ctrl[0] & DS1305_AEI0) {
+ ds1305->ctrl[0] &= ~DS1305_AEI0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+ if (status < 0)
+ return status;
+ }
+
+ /* write alarm */
+ buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC);
+ buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec);
+ buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min);
+ buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour);
+ buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE;
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x\n",
+ "alm0 write", buf[1 + DS1305_SEC], buf[1 + DS1305_MIN],
+ buf[1 + DS1305_HOUR], buf[1 + DS1305_WDAY]);
+
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+ if (status < 0)
+ return status;
+
+ /* enable alarm if requested */
+ if (alm->enabled) {
+ ds1305->ctrl[0] |= DS1305_AEI0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(ds1305->spi, buf, 2, NULL, 0);
+ }
+
+ return status;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static int ds1305_proc(struct device *dev, struct seq_file *seq)
+{
+ struct ds1305 *ds1305 = dev_get_drvdata(dev);
+ char *diodes = "no";
+ char *resistors = "";
+
+ /* ctrl[2] is treated as read-only; no locking needed */
+ if ((ds1305->ctrl[2] & 0xf0) == DS1305_TRICKLE_MAGIC) {
+ switch (ds1305->ctrl[2] & 0x0c) {
+ case DS1305_TRICKLE_DS2:
+ diodes = "2 diodes, ";
+ break;
+ case DS1305_TRICKLE_DS1:
+ diodes = "1 diode, ";
+ break;
+ default:
+ goto done;
+ }
+ switch (ds1305->ctrl[2] & 0x03) {
+ case DS1305_TRICKLE_2K:
+ resistors = "2k Ohm";
+ break;
+ case DS1305_TRICKLE_4K:
+ resistors = "4k Ohm";
+ break;
+ case DS1305_TRICKLE_8K:
+ resistors = "8k Ohm";
+ break;
+ default:
+ diodes = "no";
+ break;
+ }
+ }
+
+done:
+ return seq_printf(seq,
+ "trickle_charge\t: %s%s\n",
+ diodes, resistors);
+}
+
+#else
+#define ds1305_proc NULL
+#endif
+
+static const struct rtc_class_ops ds1305_ops = {
+ .ioctl = ds1305_ioctl,
+ .read_time = ds1305_get_time,
+ .set_time = ds1305_set_time,
+ .read_alarm = ds1305_get_alarm,
+ .set_alarm = ds1305_set_alarm,
+ .proc = ds1305_proc,
+};
+
+static void ds1305_work(struct work_struct *work)
+{
+ struct ds1305 *ds1305 = container_of(work, struct ds1305, work);
+ struct mutex *lock = &ds1305->rtc->ops_lock;
+ struct spi_device *spi = ds1305->spi;
+ u8 buf[3];
+ int status;
+
+ /* lock to protect ds1305->ctrl */
+ mutex_lock(lock);
+
+ /* Disable the IRQ, and clear its status ... for now, we "know"
+ * that if more than one alarm is active, they're in sync.
+ * Note that reading ALM data registers also clears IRQ status.
+ */
+ ds1305->ctrl[0] &= ~(DS1305_AEI1 | DS1305_AEI0);
+ ds1305->ctrl[1] = 0;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ buf[2] = 0;
+
+ status = spi_write_then_read(spi, buf, sizeof buf,
+ NULL, 0);
+ if (status < 0)
+ dev_dbg(&spi->dev, "clear irq --> %d\n", status);
+
+ mutex_unlock(lock);
+
+ if (!test_bit(FLAG_EXITING, &ds1305->flags))
+ enable_irq(spi->irq);
+
+ /* rtc_update_irq() requires an IRQ-disabled context */
+ local_irq_disable();
+ rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF);
+ local_irq_enable();
+}
+
+/*
+ * This "real" IRQ handler hands off to a workqueue mostly to allow
+ * mutex locking for ds1305->ctrl ... unlike I2C, we could issue async
+ * I/O requests in IRQ context (to clear the IRQ status).
+ */
+static irqreturn_t ds1305_irq(int irq, void *p)
+{
+ struct ds1305 *ds1305 = p;
+
+ disable_irq(irq);
+ schedule_work(&ds1305->work);
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface for NVRAM
+ */
+
+static void msg_init(struct spi_message *m, struct spi_transfer *x,
+ u8 *addr, size_t count, char *tx, char *rx)
+{
+ spi_message_init(m);
+ memset(x, 0, 2 * sizeof(*x));
+
+ x->tx_buf = addr;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+
+ x++;
+
+ x->tx_buf = tx;
+ x->rx_buf = rx;
+ x->len = count;
+ spi_message_add_tail(x, m);
+}
+
+static ssize_t
+ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct spi_device *spi;
+ u8 addr;
+ struct spi_message m;
+ struct spi_transfer x[2];
+ int status;
+
+ spi = container_of(kobj, struct spi_device, dev.kobj);
+
+ if (unlikely(off >= DS1305_NVRAM_LEN))
+ return 0;
+ if (count >= DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN;
+ if ((off + count) > DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN - off;
+ if (unlikely(!count))
+ return count;
+
+ addr = DS1305_NVRAM + off;
+ msg_init(&m, x, &addr, count, NULL, buf);
+
+ status = spi_sync(spi, &m);
+ if (status < 0)
+ dev_err(&spi->dev, "nvram %s error %d\n", "read", status);
+ return (status < 0) ? status : count;
+}
+
+static ssize_t
+ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct spi_device *spi;
+ u8 addr;
+ struct spi_message m;
+ struct spi_transfer x[2];
+ int status;
+
+ spi = container_of(kobj, struct spi_device, dev.kobj);
+
+ if (unlikely(off >= DS1305_NVRAM_LEN))
+ return -EFBIG;
+ if (count >= DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN;
+ if ((off + count) > DS1305_NVRAM_LEN)
+ count = DS1305_NVRAM_LEN - off;
+ if (unlikely(!count))
+ return count;
+
+ addr = (DS1305_WRITE | DS1305_NVRAM) + off;
+ msg_init(&m, x, &addr, count, buf, NULL);
+
+ status = spi_sync(spi, &m);
+ if (status < 0)
+ dev_err(&spi->dev, "nvram %s error %d\n", "write", status);
+ return (status < 0) ? status : count;
+}
+
+static struct bin_attribute nvram = {
+ .attr.name = "nvram",
+ .attr.mode = S_IRUGO | S_IWUSR,
+ .attr.owner = THIS_MODULE,
+ .read = ds1305_nvram_read,
+ .write = ds1305_nvram_write,
+ .size = DS1305_NVRAM_LEN,
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Interface to SPI stack
+ */
+
+static int __devinit ds1305_probe(struct spi_device *spi)
+{
+ struct ds1305 *ds1305;
+ struct rtc_device *rtc;
+ int status;
+ u8 addr, value;
+ struct ds1305_platform_data *pdata = spi->dev.platform_data;
+ bool write_ctrl = false;
+
+ /* Sanity check board setup data. This may be hooked up
+ * in 3wire mode, but we don't care. Note that unless
+ * there's an inverter in place, this needs SPI_CS_HIGH!
+ */
+ if ((spi->bits_per_word && spi->bits_per_word != 8)
+ || (spi->max_speed_hz > 2000000)
+ || !(spi->mode & SPI_CPHA))
+ return -EINVAL;
+
+ /* set up driver data */
+ ds1305 = kzalloc(sizeof *ds1305, GFP_KERNEL);
+ if (!ds1305)
+ return -ENOMEM;
+ ds1305->spi = spi;
+ spi_set_drvdata(spi, ds1305);
+
+ /* read and cache control registers */
+ addr = DS1305_CONTROL;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ ds1305->ctrl, sizeof ds1305->ctrl);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "can't %s, %d\n",
+ "read", status);
+ goto fail0;
+ }
+
+ dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+ "read", ds1305->ctrl[0],
+ ds1305->ctrl[1], ds1305->ctrl[2]);
+
+ /* Sanity check register values ... partially compensating for the
+ * fact that SPI has no device handshake. A pullup on MISO would
+ * make these tests fail; but not all systems will have one. If
+ * some register is neither 0x00 nor 0xff, a chip is likely there.
+ */
+ if ((ds1305->ctrl[0] & 0x38) != 0 || (ds1305->ctrl[1] & 0xfc) != 0) {
+ dev_dbg(&spi->dev, "RTC chip is not present\n");
+ status = -ENODEV;
+ goto fail0;
+ }
+ if (ds1305->ctrl[2] == 0)
+ dev_dbg(&spi->dev, "chip may not be present\n");
+
+ /* enable writes if needed ... if we were paranoid it would
+ * make sense to enable them only when absolutely necessary.
+ */
+ if (ds1305->ctrl[0] & DS1305_WP) {
+ u8 buf[2];
+
+ ds1305->ctrl[0] &= ~DS1305_WP;
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+
+ dev_dbg(&spi->dev, "clear WP --> %d\n", status);
+ if (status < 0)
+ goto fail0;
+ }
+
+ /* on DS1305, maybe start oscillator; like most low power
+ * oscillators, it may take a second to stabilize
+ */
+ if (ds1305->ctrl[0] & DS1305_nEOSC) {
+ ds1305->ctrl[0] &= ~DS1305_nEOSC;
+ write_ctrl = true;
+ dev_warn(&spi->dev, "SET TIME!\n");
+ }
+
+ /* ack any pending IRQs */
+ if (ds1305->ctrl[1]) {
+ ds1305->ctrl[1] = 0;
+ write_ctrl = true;
+ }
+
+ /* this may need one-time (re)init */
+ if (pdata) {
+ /* maybe enable trickle charge */
+ if (((ds1305->ctrl[2] & 0xf0) != DS1305_TRICKLE_MAGIC)) {
+ ds1305->ctrl[2] = DS1305_TRICKLE_MAGIC
+ | pdata->trickle;
+ write_ctrl = true;
+ }
+
+ /* on DS1306, configure 1 Hz signal */
+ if (pdata->is_ds1306) {
+ if (pdata->en_1hz) {
+ if (!(ds1305->ctrl[0] & DS1306_1HZ)) {
+ ds1305->ctrl[0] |= DS1306_1HZ;
+ write_ctrl = true;
+ }
+ } else {
+ if (ds1305->ctrl[0] & DS1306_1HZ) {
+ ds1305->ctrl[0] &= ~DS1306_1HZ;
+ write_ctrl = true;
+ }
+ }
+ }
+ }
+
+ if (write_ctrl) {
+ u8 buf[4];
+
+ buf[0] = DS1305_WRITE | DS1305_CONTROL;
+ buf[1] = ds1305->ctrl[0];
+ buf[2] = ds1305->ctrl[1];
+ buf[3] = ds1305->ctrl[2];
+ status = spi_write_then_read(spi, buf, sizeof buf, NULL, 0);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "can't %s, %d\n",
+ "write", status);
+ goto fail0;
+ }
+
+ dev_dbg(&spi->dev, "ctrl %s: %02x %02x %02x\n",
+ "write", ds1305->ctrl[0],
+ ds1305->ctrl[1], ds1305->ctrl[2]);
+ }
+
+ /* see if non-Linux software set up AM/PM mode */
+ addr = DS1305_HOUR;
+ status = spi_write_then_read(spi, &addr, sizeof addr,
+ &value, sizeof value);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "read HOUR --> %d\n", status);
+ goto fail0;
+ }
+
+ ds1305->hr12 = (DS1305_HR_12 & value) != 0;
+ if (ds1305->hr12)
+ dev_dbg(&spi->dev, "AM/PM\n");
+
+ /* register RTC ... from here on, ds1305->ctrl needs locking */
+ rtc = rtc_device_register("ds1305", &spi->dev,
+ &ds1305_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ status = PTR_ERR(rtc);
+ dev_dbg(&spi->dev, "register rtc --> %d\n", status);
+ goto fail0;
+ }
+ ds1305->rtc = rtc;
+
+ /* Maybe set up alarm IRQ; be ready to handle it triggering right
+ * away. NOTE that we don't share this. The signal is active low,
+ * and we can't ack it before a SPI message delay. We temporarily
+ * disable the IRQ until it's acked, which lets us work with more
+ * IRQ trigger modes (not all IRQ controllers can do falling edge).
+ */
+ if (spi->irq) {
+ INIT_WORK(&ds1305->work, ds1305_work);
+ status = request_irq(spi->irq, ds1305_irq,
+ 0, dev_name(&rtc->dev), ds1305);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "request_irq %d --> %d\n",
+ spi->irq, status);
+ goto fail1;
+ }
+ }
+
+ /* export NVRAM */
+ status = sysfs_create_bin_file(&spi->dev.kobj, &nvram);
+ if (status < 0) {
+ dev_dbg(&spi->dev, "register nvram --> %d\n", status);
+ goto fail2;
+ }
+
+ return 0;
+
+fail2:
+ free_irq(spi->irq, ds1305);
+fail1:
+ rtc_device_unregister(rtc);
+fail0:
+ kfree(ds1305);
+ return status;
+}
+
+static int __devexit ds1305_remove(struct spi_device *spi)
+{
+ struct ds1305 *ds1305 = spi_get_drvdata(spi);
+
+ sysfs_remove_bin_file(&spi->dev.kobj, &nvram);
+
+ /* carefully shut down irq and workqueue, if present */
+ if (spi->irq) {
+ set_bit(FLAG_EXITING, &ds1305->flags);
+ free_irq(spi->irq, ds1305);
+ flush_scheduled_work();
+ }
+
+ rtc_device_unregister(ds1305->rtc);
+ spi_set_drvdata(spi, NULL);
+ kfree(ds1305);
+ return 0;
+}
+
+static struct spi_driver ds1305_driver = {
+ .driver.name = "rtc-ds1305",
+ .driver.owner = THIS_MODULE,
+ .probe = ds1305_probe,
+ .remove = __devexit_p(ds1305_remove),
+ /* REVISIT add suspend/resume */
+};
+
+static int __init ds1305_init(void)
+{
+ return spi_register_driver(&ds1305_driver);
+}
+module_init(ds1305_init);
+
+static void __exit ds1305_exit(void)
+{
+ spi_unregister_driver(&ds1305_driver);
+}
+module_exit(ds1305_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 0a19c06019b..24bc1689fc7 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -13,21 +13,21 @@
*
*/
-#include <linux/module.h>
+#include <linux/bcd.h>
+#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
-#include <linux/i2c.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
#ifdef CONFIG_RTC_DRV_M41T80_WDT
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
#endif
#define M41T80_REG_SSEC 0
@@ -631,14 +631,12 @@ static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EFAULT;
if (rv & WDIOS_DISABLECARD) {
- printk(KERN_INFO
- "rtc-m41t80: disable watchdog\n");
+ pr_info("rtc-m41t80: disable watchdog\n");
wdt_disable();
}
if (rv & WDIOS_ENABLECARD) {
- printk(KERN_INFO
- "rtc-m41t80: enable watchdog\n");
+ pr_info("rtc-m41t80: enable watchdog\n");
wdt_ping();
}
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
new file mode 100644
index 00000000000..9b19499c829
--- /dev/null
+++ b/drivers/rtc/rtc-m41t94.c
@@ -0,0 +1,173 @@
+/*
+ * Driver for ST M41T94 SPI RTC
+ *
+ * Copyright (C) 2008 Kim B. Heino
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define M41T94_REG_SECONDS 0x01
+#define M41T94_REG_MINUTES 0x02
+#define M41T94_REG_HOURS 0x03
+#define M41T94_REG_WDAY 0x04
+#define M41T94_REG_DAY 0x05
+#define M41T94_REG_MONTH 0x06
+#define M41T94_REG_YEAR 0x07
+#define M41T94_REG_HT 0x0c
+
+#define M41T94_BIT_HALT 0x40
+#define M41T94_BIT_STOP 0x80
+#define M41T94_BIT_CB 0x40
+#define M41T94_BIT_CEB 0x80
+
+static int m41t94_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ u8 buf[8]; /* write cmd + 7 registers */
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "write", tm->tm_sec, tm->tm_min,
+ tm->tm_hour, tm->tm_mday,
+ tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */
+ buf[M41T94_REG_SECONDS] = BIN2BCD(tm->tm_sec);
+ buf[M41T94_REG_MINUTES] = BIN2BCD(tm->tm_min);
+ buf[M41T94_REG_HOURS] = BIN2BCD(tm->tm_hour);
+ buf[M41T94_REG_WDAY] = BIN2BCD(tm->tm_wday + 1);
+ buf[M41T94_REG_DAY] = BIN2BCD(tm->tm_mday);
+ buf[M41T94_REG_MONTH] = BIN2BCD(tm->tm_mon + 1);
+
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
+ if (tm->tm_year >= 100)
+ buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
+ buf[M41T94_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+
+ return spi_write(spi, buf, 8);
+}
+
+static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ u8 buf[2];
+ int ret, hour;
+
+ /* clear halt update bit */
+ ret = spi_w8r8(spi, M41T94_REG_HT);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_HALT) {
+ buf[0] = 0x80 | M41T94_REG_HT;
+ buf[1] = ret & ~M41T94_BIT_HALT;
+ spi_write(spi, buf, 2);
+ }
+
+ /* clear stop bit */
+ ret = spi_w8r8(spi, M41T94_REG_SECONDS);
+ if (ret < 0)
+ return ret;
+ if (ret & M41T94_BIT_STOP) {
+ buf[0] = 0x80 | M41T94_REG_SECONDS;
+ buf[1] = ret & ~M41T94_BIT_STOP;
+ spi_write(spi, buf, 2);
+ }
+
+ tm->tm_sec = BCD2BIN(spi_w8r8(spi, M41T94_REG_SECONDS));
+ tm->tm_min = BCD2BIN(spi_w8r8(spi, M41T94_REG_MINUTES));
+ hour = spi_w8r8(spi, M41T94_REG_HOURS);
+ tm->tm_hour = BCD2BIN(hour & 0x3f);
+ tm->tm_wday = BCD2BIN(spi_w8r8(spi, M41T94_REG_WDAY)) - 1;
+ tm->tm_mday = BCD2BIN(spi_w8r8(spi, M41T94_REG_DAY));
+ tm->tm_mon = BCD2BIN(spi_w8r8(spi, M41T94_REG_MONTH)) - 1;
+ tm->tm_year = BCD2BIN(spi_w8r8(spi, M41T94_REG_YEAR));
+ if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
+ tm->tm_year += 100;
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "read", tm->tm_sec, tm->tm_min,
+ tm->tm_hour, tm->tm_mday,
+ tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+ /* initial clock setting can be undefined */
+ return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops m41t94_rtc_ops = {
+ .read_time = m41t94_read_time,
+ .set_time = m41t94_set_time,
+};
+
+static struct spi_driver m41t94_driver;
+
+static int __devinit m41t94_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ int res;
+
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ res = spi_w8r8(spi, M41T94_REG_SECONDS);
+ if (res < 0) {
+ dev_err(&spi->dev, "not found.\n");
+ return res;
+ }
+
+ rtc = rtc_device_register(m41t94_driver.driver.name,
+ &spi->dev, &m41t94_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ dev_set_drvdata(&spi->dev, rtc);
+
+ return 0;
+}
+
+static int __devexit m41t94_remove(struct spi_device *spi)
+{
+ struct rtc_device *rtc = platform_get_drvdata(spi);
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ return 0;
+}
+
+static struct spi_driver m41t94_driver = {
+ .driver = {
+ .name = "rtc-m41t94",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = m41t94_probe,
+ .remove = __devexit_p(m41t94_remove),
+};
+
+static __init int m41t94_init(void)
+{
+ return spi_register_driver(&m41t94_driver);
+}
+
+module_init(m41t94_init);
+
+static __exit void m41t94_exit(void)
+{
+ spi_unregister_driver(&m41t94_driver);
+}
+
+module_exit(m41t94_exit);
+
+MODULE_AUTHOR("Kim B. Heino <Kim.Heino@bluegiga.com>");
+MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index eb23d8423f4..8876605d4d4 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -92,18 +92,6 @@
#define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr))
-/* platform_bus isn't hotpluggable, so for static linkage it'd be safe
- * to get rid of probe() and remove() code ... too bad the driver struct
- * remembers probe(), that's about 25% of the runtime footprint!!
- */
-#ifndef MODULE
-#undef __devexit
-#undef __devexit_p
-#define __devexit __exit
-#define __devexit_p __exit_p
-#endif
-
-
/* we rely on the rtc framework to handle locking (rtc->ops_lock),
* so the only other requirement is that register accesses which
* require BUSY to be clear are made with IRQs locally disabled
@@ -324,7 +312,7 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;
-static int __devinit omap_rtc_probe(struct platform_device *pdev)
+static int __init omap_rtc_probe(struct platform_device *pdev)
{
struct resource *res, *mem;
struct rtc_device *rtc;
@@ -440,7 +428,7 @@ fail:
return -EIO;
}
-static int __devexit omap_rtc_remove(struct platform_device *pdev)
+static int __exit omap_rtc_remove(struct platform_device *pdev)
{
struct rtc_device *rtc = platform_get_drvdata(pdev);;
@@ -498,8 +486,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
MODULE_ALIAS("platform:omap_rtc");
static struct platform_driver omap_rtc_driver = {
- .probe = omap_rtc_probe,
- .remove = __devexit_p(omap_rtc_remove),
+ .remove = __exit_p(omap_rtc_remove),
.suspend = omap_rtc_suspend,
.resume = omap_rtc_resume,
.shutdown = omap_rtc_shutdown,
@@ -511,7 +498,7 @@ static struct platform_driver omap_rtc_driver = {
static int __init rtc_init(void)
{
- return platform_driver_register(&omap_rtc_driver);
+ return platform_driver_probe(&omap_rtc_driver, omap_rtc_probe);
}
module_init(rtc_init);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 3d09d8f0b1f..d388c662bf4 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -2,6 +2,7 @@
* drivers/rtc/rtc-pcf8583.c
*
* Copyright (C) 2000 Russell King
+ * Copyright (C) 2008 Wolfram Sang & Juergen Beisert, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,7 +15,6 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
-#include <linux/string.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -27,7 +27,6 @@ struct rtc_mem {
};
struct pcf8583 {
- struct i2c_client client;
struct rtc_device *rtc;
unsigned char ctrl;
};
@@ -40,10 +39,6 @@ struct pcf8583 {
#define CTRL_ALARM 0x02
#define CTRL_TIMER 0x01
-static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
-
-/* Module parameters */
-I2C_CLIENT_INSMOD;
static struct i2c_driver pcf8583_driver;
@@ -269,106 +264,60 @@ static const struct rtc_class_ops pcf8583_rtc_ops = {
.set_time = pcf8583_rtc_set_time,
};
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
-
-static int pcf8583_attach(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, pcf8583_probe);
-}
-
-static int pcf8583_detach(struct i2c_client *client)
-{
- int err;
- struct pcf8583 *pcf = i2c_get_clientdata(client);
- struct rtc_device *rtc = pcf->rtc;
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(pcf);
- return 0;
-}
-
-static struct i2c_driver pcf8583_driver = {
- .driver = {
- .name = "pcf8583",
- },
- .id = I2C_DRIVERID_PCF8583,
- .attach_adapter = pcf8583_attach,
- .detach_client = pcf8583_detach,
-};
-
-static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+static int pcf8583_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct pcf8583 *pcf;
- struct i2c_client *client;
- struct rtc_device *rtc;
- unsigned char buf[1], ad[1] = { 0 };
+ struct pcf8583 *pcf8583;
int err;
- struct i2c_msg msgs[2] = {
- {
- .addr = addr,
- .flags = 0,
- .len = 1,
- .buf = ad,
- }, {
- .addr = addr,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = buf,
- }
- };
- if (!i2c_check_functionality(adap, I2C_FUNC_I2C))
- return 0;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
- pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
- if (!pcf)
+ pcf8583 = kzalloc(sizeof(struct pcf8583), GFP_KERNEL);
+ if (!pcf8583)
return -ENOMEM;
- client = &pcf->client;
+ pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name,
+ &client->dev, &pcf8583_rtc_ops, THIS_MODULE);
- client->addr = addr;
- client->adapter = adap;
- client->driver = &pcf8583_driver;
-
- strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
-
- if (i2c_transfer(client->adapter, msgs, 2) != 2) {
- err = -EIO;
+ if (IS_ERR(pcf8583->rtc)) {
+ err = PTR_ERR(pcf8583->rtc);
goto exit_kfree;
}
- err = i2c_attach_client(client);
-
- if (err)
- goto exit_kfree;
-
- rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
- &pcf8583_rtc_ops, THIS_MODULE);
+ i2c_set_clientdata(client, pcf8583);
+ return 0;
- if (IS_ERR(rtc)) {
- err = PTR_ERR(rtc);
- goto exit_detach;
- }
+exit_kfree:
+ kfree(pcf8583);
+ return err;
+}
- pcf->rtc = rtc;
- i2c_set_clientdata(client, pcf);
- set_ctrl(client, buf[0]);
+static int __devexit pcf8583_remove(struct i2c_client *client)
+{
+ struct pcf8583 *pcf8583 = i2c_get_clientdata(client);
+ if (pcf8583->rtc)
+ rtc_device_unregister(pcf8583->rtc);
+ kfree(pcf8583);
return 0;
+}
-exit_detach:
- i2c_detach_client(client);
-
-exit_kfree:
- kfree(pcf);
+static const struct i2c_device_id pcf8583_id[] = {
+ { "pcf8583", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8583_id);
- return err;
-}
+static struct i2c_driver pcf8583_driver = {
+ .driver = {
+ .name = "pcf8583",
+ .owner = THIS_MODULE,
+ },
+ .probe = pcf8583_probe,
+ .remove = __devexit_p(pcf8583_remove),
+ .id_table = pcf8583_id,
+};
static __init int pcf8583_init(void)
{
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index fed86e507fd..54b1ebb0150 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -36,10 +36,8 @@ static struct resource *s3c_rtc_mem;
static void __iomem *s3c_rtc_base;
static int s3c_rtc_alarmno = NO_IRQ;
static int s3c_rtc_tickno = NO_IRQ;
-static int s3c_rtc_freq = 1;
static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
-static unsigned int tick_count;
/* IRQ Handlers */
@@ -55,7 +53,7 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
struct rtc_device *rdev = id;
- rtc_update_irq(rdev, tick_count++, RTC_PF | RTC_IRQF);
+ rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
return IRQ_HANDLED;
}
@@ -74,35 +72,37 @@ static void s3c_rtc_setaie(int to)
writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
}
-static void s3c_rtc_setpie(int to)
+static int s3c_rtc_setpie(struct device *dev, int enabled)
{
unsigned int tmp;
- pr_debug("%s: pie=%d\n", __func__, to);
+ pr_debug("%s: pie=%d\n", __func__, enabled);
spin_lock_irq(&s3c_rtc_pie_lock);
tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
- if (to)
+ if (enabled)
tmp |= S3C2410_TICNT_ENABLE;
writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
+
+ return 0;
}
-static void s3c_rtc_setfreq(int freq)
+static int s3c_rtc_setfreq(struct device *dev, int freq)
{
unsigned int tmp;
spin_lock_irq(&s3c_rtc_pie_lock);
- tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
-
- s3c_rtc_freq = freq;
+ tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
tmp |= (128 / freq)-1;
writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
+
+ return 0;
}
/* Time read/write */
@@ -267,12 +267,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(alrm_en, base + S3C2410_RTCALM);
- if (0) {
- alrm_en = readb(base + S3C2410_RTCALM);
- alrm_en &= ~S3C2410_RTCALM_ALMEN;
- writeb(alrm_en, base + S3C2410_RTCALM);
- disable_irq_wake(s3c_rtc_alarmno);
- }
+ s3c_rtc_setaie(alrm->enabled);
if (alrm->enabled)
enable_irq_wake(s3c_rtc_alarmno);
@@ -282,59 +277,12 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
return 0;
}
-static int s3c_rtc_ioctl(struct device *dev,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int ret = -ENOIOCTLCMD;
-
- switch (cmd) {
- case RTC_AIE_OFF:
- case RTC_AIE_ON:
- s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0);
- ret = 0;
- break;
-
- case RTC_PIE_OFF:
- case RTC_PIE_ON:
- tick_count = 0;
- s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0);
- ret = 0;
- break;
-
- case RTC_IRQP_READ:
- ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg);
- break;
-
- case RTC_IRQP_SET:
- if (!is_power_of_2(arg)) {
- ret = -EINVAL;
- goto exit;
- }
-
- pr_debug("s3c2410_rtc: setting frequency %ld\n", arg);
-
- s3c_rtc_setfreq(arg);
- ret = 0;
- break;
-
- case RTC_UIE_ON:
- case RTC_UIE_OFF:
- ret = -EINVAL;
- }
-
- exit:
- return ret;
-}
-
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
seq_printf(seq, "periodic_IRQ\t: %s\n",
(ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" );
-
- seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq);
-
return 0;
}
@@ -374,7 +322,7 @@ static void s3c_rtc_release(struct device *dev)
/* do not clear AIE here, it may be needed for wake */
- s3c_rtc_setpie(0);
+ s3c_rtc_setpie(dev, 0);
free_irq(s3c_rtc_alarmno, rtc_dev);
free_irq(s3c_rtc_tickno, rtc_dev);
}
@@ -382,11 +330,12 @@ static void s3c_rtc_release(struct device *dev)
static const struct rtc_class_ops s3c_rtcops = {
.open = s3c_rtc_open,
.release = s3c_rtc_release,
- .ioctl = s3c_rtc_ioctl,
.read_time = s3c_rtc_gettime,
.set_time = s3c_rtc_settime,
.read_alarm = s3c_rtc_getalarm,
.set_alarm = s3c_rtc_setalarm,
+ .irq_set_freq = s3c_rtc_setfreq,
+ .irq_set_state = s3c_rtc_setpie,
.proc = s3c_rtc_proc,
};
@@ -430,14 +379,14 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
}
}
-static int s3c_rtc_remove(struct platform_device *dev)
+static int __devexit s3c_rtc_remove(struct platform_device *dev)
{
struct rtc_device *rtc = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
rtc_device_unregister(rtc);
- s3c_rtc_setpie(0);
+ s3c_rtc_setpie(&dev->dev, 0);
s3c_rtc_setaie(0);
iounmap(s3c_rtc_base);
@@ -447,7 +396,7 @@ static int s3c_rtc_remove(struct platform_device *dev)
return 0;
}
-static int s3c_rtc_probe(struct platform_device *pdev)
+static int __devinit s3c_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
struct resource *res;
@@ -504,7 +453,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
pr_debug("s3c2410_rtc: RTCCON=%02x\n",
readb(s3c_rtc_base + S3C2410_RTCCON));
- s3c_rtc_setfreq(s3c_rtc_freq);
+ s3c_rtc_setfreq(&pdev->dev, 1);
/* register RTC and exit */
@@ -560,7 +509,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
static struct platform_driver s3c2410_rtcdrv = {
.probe = s3c_rtc_probe,
- .remove = s3c_rtc_remove,
+ .remove = __devexit_p(s3c_rtc_remove),
.suspend = s3c_rtc_suspend,
.resume = s3c_rtc_resume,
.driver = {
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index be9c70d0b19..884b635f028 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* 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
@@ -34,7 +34,7 @@
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
/* RTC 1 registers */
#define ETIMELREG 0x00
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
static DEFINE_SPINLOCK(rtc_lock);
static char rtc_name[] = "RTC";
-static unsigned long periodic_frequency;
static unsigned long periodic_count;
static unsigned int alarm_enabled;
static int aie_irq = -1;
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
return 0;
}
-static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
{
unsigned long count;
+ count = RTC_FREQUENCY;
+ do_div(count, freq);
+
+ periodic_count = count;
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(RTCL1LREG, count);
+ rtc1_write(RTCL1HREG, count >> 16);
+
+ spin_unlock_irq(&rtc_lock);
+
+ return 0;
+}
+
+static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
+{
+ if (enabled)
+ enable_irq(pie_irq);
+ else
+ disable_irq(pie_irq);
+
+ return 0;
+}
+
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
switch (cmd) {
case RTC_AIE_ON:
spin_lock_irq(&rtc_lock);
@@ -232,33 +258,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
spin_unlock_irq(&rtc_lock);
break;
- case RTC_PIE_ON:
- enable_irq(pie_irq);
- break;
- case RTC_PIE_OFF:
- disable_irq(pie_irq);
- break;
- case RTC_IRQP_READ:
- return put_user(periodic_frequency, (unsigned long __user *)arg);
- break;
- case RTC_IRQP_SET:
- if (arg > MAX_PERIODIC_RATE)
- return -EINVAL;
-
- periodic_frequency = arg;
-
- count = RTC_FREQUENCY;
- do_div(count, arg);
-
- periodic_count = count;
-
- spin_lock_irq(&rtc_lock);
-
- rtc1_write(RTCL1LREG, count);
- rtc1_write(RTCL1HREG, count >> 16);
-
- spin_unlock_irq(&rtc_lock);
- break;
case RTC_EPOCH_READ:
return put_user(epoch, (unsigned long __user *)arg);
case RTC_EPOCH_SET:
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
.set_time = vr41xx_rtc_set_time,
.read_alarm = vr41xx_rtc_read_alarm,
.set_alarm = vr41xx_rtc_set_alarm,
+ .irq_set_freq = vr41xx_rtc_irq_set_freq,
+ .irq_set_state = vr41xx_rtc_irq_set_state,
};
static int __devinit rtc_probe(struct platform_device *pdev)
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev)
goto err_iounmap_all;
}
+ rtc->max_user_freq = MAX_PERIODIC_RATE;
+
spin_lock_irq(&rtc_lock);
rtc1_write(ECMPLREG, 0);
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 81a96e01908..c3dee900a5c 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1168,17 +1168,19 @@ static int raw3270_create_attributes(struct raw3270 *rp)
if (rc)
goto out;
- rp->clttydev = device_create(class3270, &rp->cdev->dev,
- MKDEV(IBM_TTY3270_MAJOR, rp->minor),
- "tty%s", rp->cdev->dev.bus_id);
+ rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
+ MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+ NULL,
+ "tty%s", rp->cdev->dev.bus_id);
if (IS_ERR(rp->clttydev)) {
rc = PTR_ERR(rp->clttydev);
goto out_ttydev;
}
- rp->cltubdev = device_create(class3270, &rp->cdev->dev,
- MKDEV(IBM_FS3270_MAJOR, rp->minor),
- "tub%s", rp->cdev->dev.bus_id);
+ rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
+ MKDEV(IBM_FS3270_MAJOR, rp->minor),
+ NULL,
+ "tub%s", rp->cdev->dev.bus_id);
if (!IS_ERR(rp->cltubdev))
goto out;
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 6dfdb7c1798..12c2a5aaf31 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,10 +69,9 @@ struct tape_class_device *register_tape_dev(
if (rc)
goto fail_with_cdev;
- tcd->class_device = device_create(tape_class, device,
- tcd->char_device->dev,
- "%s", tcd->device_name
- );
+ tcd->class_device = device_create_drvdata(tape_class, device,
+ tcd->char_device->dev,
+ NULL, "%s", tcd->device_name);
rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
if (rc)
goto fail_with_cdev;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index b0ac44b2712..c1f352b8486 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -896,8 +896,9 @@ static int ur_set_online(struct ccw_device *cdev)
goto fail_free_cdev;
}
- urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
- "%s", node_id);
+ urd->device = device_create_drvdata(vmur_class, NULL,
+ urd->char_device->dev, NULL,
+ "%s", node_id);
if (IS_ERR(urd->device)) {
rc = PTR_ERR(urd->device);
TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index c644669a75c..a08b1682c8e 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -58,13 +58,13 @@
* 1.10 Changes for Buffer allocation
* 1.15 Changed for 2.6 Kernel No longer compiles on 2.4 or lower
* 1.25 Added Packing support
+ * 1.5
*/
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
#include <asm/debug.h>
#include <asm/idals.h>
#include <asm/io.h>
-
#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/delay.h>
@@ -90,36 +90,10 @@
#include "cu3088.h"
#include "claw.h"
-MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
-MODULE_DESCRIPTION("Linux for zSeries CLAW Driver\n" \
- "Copyright 2000,2005 IBM Corporation\n");
-MODULE_LICENSE("GPL");
-
-/* Debugging is based on DEBUGMSG, IOTRACE, or FUNCTRACE options:
- DEBUGMSG - Enables output of various debug messages in the code
- IOTRACE - Enables output of CCW and other IO related traces
- FUNCTRACE - Enables output of function entry/exit trace
- Define any combination of above options to enable tracing
-
- CLAW also uses the s390dbf file system see claw_trace and claw_setup
+/*
+ CLAW uses the s390dbf file system see claw_trace and claw_setup
*/
-/* following enables tracing */
-//#define DEBUGMSG
-//#define IOTRACE
-//#define FUNCTRACE
-
-#ifdef DEBUGMSG
-#define DEBUG
-#endif
-
-#ifdef IOTRACE
-#define DEBUG
-#endif
-
-#ifdef FUNCTRACE
-#define DEBUG
-#endif
static char debug_buffer[255];
/**
@@ -146,7 +120,6 @@ claw_register_debug_facility(void)
claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
- printk(KERN_WARNING "Not enough memory for debug facility.\n");
claw_unregister_debug_facility();
return -ENOMEM;
}
@@ -232,9 +205,6 @@ static void probe_error( struct ccwgroup_device *cgdev);
static struct net_device_stats *claw_stats(struct net_device *dev);
static int pages_to_order_of_mag(int num_of_pages);
static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
-#ifdef DEBUG
-static void dumpit (char *buf, int len);
-#endif
/* sysfs Functions */
static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
@@ -263,12 +233,12 @@ static int claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl);
static int claw_snd_sys_validate_rsp(struct net_device *dev,
struct clawctl * p_ctl, __u32 return_code);
static int claw_strt_conn_req(struct net_device *dev );
-static void claw_strt_read ( struct net_device *dev, int lock );
-static void claw_strt_out_IO( struct net_device *dev );
-static void claw_free_wrt_buf( struct net_device *dev );
+static void claw_strt_read(struct net_device *dev, int lock);
+static void claw_strt_out_IO(struct net_device *dev);
+static void claw_free_wrt_buf(struct net_device *dev);
/* Functions for unpack reads */
-static void unpack_read (struct net_device *dev );
+static void unpack_read(struct net_device *dev);
/* ccwgroup table */
@@ -284,7 +254,6 @@ static struct ccwgroup_driver claw_group_driver = {
};
/*
-*
* Key functions
*/
@@ -298,23 +267,14 @@ claw_probe(struct ccwgroup_device *cgdev)
int rc;
struct claw_privbk *privptr=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter\n",__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"probe");
+ CLAW_DBF_TEXT(2, setup, "probe");
if (!get_device(&cgdev->dev))
return -ENODEV;
-#ifdef DEBUGMSG
- printk(KERN_INFO "claw: variable cgdev =\n");
- dumpit((char *)cgdev, sizeof(struct ccwgroup_device));
-#endif
privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
if (privptr == NULL) {
probe_error(cgdev);
put_device(&cgdev->dev);
- printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
return -ENOMEM;
}
privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
@@ -322,9 +282,7 @@ claw_probe(struct ccwgroup_device *cgdev)
if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
probe_error(cgdev);
put_device(&cgdev->dev);
- printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
- cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
return -ENOMEM;
}
memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
@@ -341,19 +299,14 @@ claw_probe(struct ccwgroup_device *cgdev)
put_device(&cgdev->dev);
printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
- CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+ CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
return rc;
}
- printk(KERN_INFO "claw: sysfs files added for %s\n",cgdev->cdev[0]->dev.bus_id);
privptr->p_env->p_priv = privptr;
cgdev->cdev[0]->handler = claw_irq_handler;
cgdev->cdev[1]->handler = claw_irq_handler;
cgdev->dev.driver_data = privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw:%s exit on line %d, "
- "rc = 0\n",__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,setup,"prbext 0");
+ CLAW_DBF_TEXT(2, setup, "prbext 0");
return 0;
} /* end of claw_probe */
@@ -370,37 +323,18 @@ claw_tx(struct sk_buff *skb, struct net_device *dev)
unsigned long saveflags;
struct chbk *p_ch;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"claw_tx");
+ CLAW_DBF_TEXT(4, trace, "claw_tx");
p_ch=&privptr->channel[WRITE];
if (skb == NULL) {
- printk(KERN_WARNING "%s: null pointer passed as sk_buffer\n",
- dev->name);
privptr->stats.tx_dropped++;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
- dev->name,__func__, __LINE__);
-#endif
- CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+ privptr->stats.tx_errors++;
+ CLAW_DBF_TEXT_(2, trace, "clawtx%d", -EIO);
return -EIO;
}
-
-#ifdef IOTRACE
- printk(KERN_INFO "%s: variable sk_buff=\n",dev->name);
- dumpit((char *) skb, sizeof(struct sk_buff));
- printk(KERN_INFO "%s: variable dev=\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
rc=claw_hw_tx( skb, dev, 1 );
spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
- dev->name, __func__, __LINE__, rc);
-#endif
- CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+ CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc);
return rc;
} /* end of claw_tx */
@@ -419,7 +353,7 @@ claw_pack_skb(struct claw_privbk *privptr)
new_skb = NULL; /* assume no dice */
pkt_cnt = 0;
- CLAW_DBF_TEXT(4,trace,"PackSKBe");
+ CLAW_DBF_TEXT(4, trace, "PackSKBe");
if (!skb_queue_empty(&p_ch->collect_queue)) {
/* some data */
held_skb = skb_dequeue(&p_ch->collect_queue);
@@ -457,13 +391,8 @@ claw_pack_skb(struct claw_privbk *privptr)
skb_queue_head(&p_ch->collect_queue,held_skb);
}
}
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() Packed %d len %d\n",
- p_env->ndev->name,
- __func__,pkt_cnt,new_skb->len);
-#endif
}
- CLAW_DBF_TEXT(4,trace,"PackSKBx");
+ CLAW_DBF_TEXT(4, trace, "PackSKBx");
return new_skb;
}
@@ -477,29 +406,12 @@ claw_change_mtu(struct net_device *dev, int new_mtu)
{
struct claw_privbk *privptr=dev->priv;
int buff_size;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "variable dev =\n");
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "variable new_mtu = %d\n", new_mtu);
-#endif
- CLAW_DBF_TEXT(4,trace,"setmtu");
+ CLAW_DBF_TEXT(4, trace, "setmtu");
buff_size = privptr->p_env->write_size;
if ((new_mtu < 60) || (new_mtu > buff_size)) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
- dev->name,
- __func__, __LINE__);
-#endif
return -EINVAL;
}
dev->mtu = new_mtu;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
- __func__, __LINE__);
-#endif
return 0;
} /* end of claw_change_mtu */
@@ -521,24 +433,13 @@ claw_open(struct net_device *dev)
struct timer_list timer;
struct ccwbk *p_buf;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"open");
- if (!dev || (dev->name[0] == 0x00)) {
- CLAW_DBF_TEXT(2,trace,"BadDev");
- printk(KERN_WARNING "claw: Bad device at open failing \n");
- return -ENODEV;
- }
+ CLAW_DBF_TEXT(4, trace, "open");
privptr = (struct claw_privbk *)dev->priv;
/* allocate and initialize CCW blocks */
if (privptr->buffs_alloc == 0) {
rc=init_ccw_bk(dev);
if (rc) {
- printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
- dev->name,
- __func__, __LINE__);
- CLAW_DBF_TEXT(2,trace,"openmem");
+ CLAW_DBF_TEXT(2, trace, "openmem");
return -ENOMEM;
}
}
@@ -557,7 +458,7 @@ claw_open(struct net_device *dev)
tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet,
(unsigned long) &privptr->channel[READ]);
for ( i = 0; i < 2; i++) {
- CLAW_DBF_TEXT_(2,trace,"opn_ch%d",i);
+ CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i);
init_waitqueue_head(&privptr->channel[i].wait);
/* skb_queue_head_init(&p_ch->io_queue); */
if (i == WRITE)
@@ -595,15 +496,8 @@ claw_open(struct net_device *dev)
~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
(((privptr->channel[READ].flag |
privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: channel problems during open - read:"
- " %02x - write: %02x\n",
- dev->name,
- privptr->channel[READ].last_dstat,
- privptr->channel[WRITE].last_dstat);
-#endif
printk(KERN_INFO "%s: remote side is not ready\n", dev->name);
- CLAW_DBF_TEXT(2,trace,"notrdy");
+ CLAW_DBF_TEXT(2, trace, "notrdy");
for ( i = 0; i < 2; i++) {
spin_lock_irqsave(
@@ -659,23 +553,14 @@ claw_open(struct net_device *dev)
privptr->p_buff_read=NULL;
privptr->p_buff_write=NULL;
claw_clear_busy(dev);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"open EIO");
+ CLAW_DBF_TEXT(2, trace, "open EIO");
return -EIO;
}
/* Send SystemValidate command */
claw_clear_busy(dev);
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"openok");
+ CLAW_DBF_TEXT(4, trace, "openok");
return 0;
} /* end of claw_open */
@@ -694,22 +579,14 @@ claw_irq_handler(struct ccw_device *cdev,
struct claw_env *p_env;
struct chbk *p_ch_r=NULL;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"clawirq");
+ CLAW_DBF_TEXT(4, trace, "clawirq");
/* Bypass all 'unsolicited interrupts' */
if (!cdev->dev.driver_data) {
printk(KERN_WARNING "claw: unsolicited interrupt for device:"
"%s received c-%02x d-%02x\n",
cdev->dev.bus_id, irb->scsw.cmd.cstat,
irb->scsw.cmd.dstat);
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() "
- "exit on line %d\n",__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"badirq");
+ CLAW_DBF_TEXT(2, trace, "badirq");
return;
}
privptr = (struct claw_privbk *)cdev->dev.driver_data;
@@ -722,41 +599,25 @@ claw_irq_handler(struct ccw_device *cdev,
else {
printk(KERN_WARNING "claw: Can't determine channel for "
"interrupt, device %s\n", cdev->dev.bus_id);
- CLAW_DBF_TEXT(2,trace,"badchan");
+ CLAW_DBF_TEXT(2, trace, "badchan");
return;
}
- CLAW_DBF_TEXT_(4,trace,"IRQCH=%d",p_ch->flag);
+ CLAW_DBF_TEXT_(4, trace, "IRQCH=%d", p_ch->flag);
dev = (struct net_device *) (p_ch->ndev);
p_env=privptr->p_env;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: interrupt for device: %04x "
- "received c-%02x d-%02x state-%02x\n",
- dev->name, p_ch->devno, irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat, p_ch->claw_state);
-#endif
-
/* Copy interruption response block. */
memcpy(p_ch->irb, irb, sizeof(struct irb));
- /* Check for good subchannel return code, otherwise error message */
+ /* Check for good subchannel return code, otherwise info message */
if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) {
printk(KERN_INFO "%s: subchannel check for device: %04x -"
" Sch Stat %02x Dev Stat %02x CPA - %04x\n",
dev->name, p_ch->devno,
irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
irb->scsw.cmd.cpa);
-#ifdef IOTRACE
- dumpit((char *)irb,sizeof(struct irb));
- dumpit((char *)(unsigned long)irb->scsw.cmd.cpa,
- sizeof(struct ccw1));
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"chanchk");
+ CLAW_DBF_TEXT(2, trace, "chanchk");
/* return; */
}
@@ -768,233 +629,138 @@ claw_irq_handler(struct ccw_device *cdev,
p_ch->last_dstat = irb->scsw.cmd.dstat;
switch (p_ch->claw_state) {
- case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: CLAW_STOP enter\n", dev->name);
-#endif
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- return;
- }
- wake_up(&p_ch->wait); /* wake up claw_release */
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: CLAW_STOP exit\n", dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"stop");
- return;
-
- case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO\n",
- dev->name);
-#endif
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"haltio");
- return;
- }
- if (p_ch->flag == CLAW_READ) {
- p_ch->claw_state = CLAW_START_READ;
- wake_up(&p_ch->wait); /* wake claw_open (READ)*/
- }
+ case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))))
+ return;
+ wake_up(&p_ch->wait); /* wake up claw_release */
+ CLAW_DBF_TEXT(4, trace, "stop");
+ return;
+ case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open */
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "haltio");
+ return;
+ }
+ if (p_ch->flag == CLAW_READ) {
+ p_ch->claw_state = CLAW_START_READ;
+ wake_up(&p_ch->wait); /* wake claw_open (READ)*/
+ } else if (p_ch->flag == CLAW_WRITE) {
+ p_ch->claw_state = CLAW_START_WRITE;
+ /* send SYSTEM_VALIDATE */
+ claw_strt_read(dev, LOCK_NO);
+ claw_send_control(dev,
+ SYSTEM_VALIDATE_REQUEST,
+ 0, 0, 0,
+ p_env->host_name,
+ p_env->adapter_name);
+ } else {
+ printk(KERN_WARNING "claw: unsolicited "
+ "interrupt for device:"
+ "%s received c-%02x d-%02x\n",
+ cdev->dev.bus_id,
+ irb->scsw.cmd.cstat,
+ irb->scsw.cmd.dstat);
+ return;
+ }
+ CLAW_DBF_TEXT(4, trace, "haltio");
+ return;
+ case CLAW_START_READ:
+ CLAW_DBF_TEXT(4, trace, "ReadIRQ");
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
+ (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
+ (p_ch->irb->ecw[0]) == 0) {
+ privptr->stats.rx_errors++;
+ printk(KERN_INFO "%s: Restart is "
+ "required after remote "
+ "side recovers \n",
+ dev->name);
+ }
+ CLAW_DBF_TEXT(4, trace, "notrdy");
+ return;
+ }
+ if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
+ (p_ch->irb->scsw.cmd.dstat == 0)) {
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0)
+ tasklet_schedule(&p_ch->tasklet);
else
- if (p_ch->flag == CLAW_WRITE) {
- p_ch->claw_state = CLAW_START_WRITE;
- /* send SYSTEM_VALIDATE */
- claw_strt_read(dev, LOCK_NO);
- claw_send_control(dev,
- SYSTEM_VALIDATE_REQUEST,
- 0, 0, 0,
- p_env->host_name,
- p_env->adapter_name );
- } else {
- printk(KERN_WARNING "claw: unsolicited "
- "interrupt for device:"
- "%s received c-%02x d-%02x\n",
- cdev->dev.bus_id,
- irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
- return;
- }
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"haltio");
- return;
- case CLAW_START_READ:
- CLAW_DBF_TEXT(4,trace,"ReadIRQ");
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- clear_bit(0, (void *)&p_ch->IO_active);
- if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
- (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
- (p_ch->irb->ecw[0]) == 0)
- {
- privptr->stats.rx_errors++;
- printk(KERN_INFO "%s: Restart is "
- "required after remote "
- "side recovers \n",
- dev->name);
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"notrdy");
- return;
- }
- if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
- (p_ch->irb->scsw.cmd.dstat == 0)) {
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch->flag_a) == 0) {
- tasklet_schedule(&p_ch->tasklet);
- }
- else {
- CLAW_DBF_TEXT(4,trace,"PCINoBH");
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"PCI_read");
- return;
- }
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"SPend_rd");
- return;
- }
- clear_bit(0, (void *)&p_ch->IO_active);
- claw_clearbit_busy(TB_RETRY,dev);
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch->flag_a) == 0) {
- tasklet_schedule(&p_ch->tasklet);
- }
- else {
- CLAW_DBF_TEXT(4,trace,"RdBHAct");
- }
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_START_READ exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"RdIRQXit");
- return;
- case CLAW_START_WRITE:
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
- printk(KERN_INFO "%s: Unit Check Occured in "
- "write channel\n",dev->name);
- clear_bit(0, (void *)&p_ch->IO_active);
- if (p_ch->irb->ecw[0] & 0x80 ) {
- printk(KERN_INFO "%s: Resetting Event "
- "occurred:\n",dev->name);
- init_timer(&p_ch->timer);
- p_ch->timer.function =
- (void *)claw_write_retry;
- p_ch->timer.data = (unsigned long)p_ch;
- p_ch->timer.expires = jiffies + 10*HZ;
- add_timer(&p_ch->timer);
- printk(KERN_INFO "%s: write connection "
- "restarting\n",dev->name);
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rstrtwrt");
- return;
- }
- if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
- clear_bit(0, (void *)&p_ch->IO_active);
- printk(KERN_INFO "%s: Unit Exception "
- "Occured in write channel\n",
- dev->name);
- }
- if (!((p_ch->irb->scsw.cmd.stctl &
- SCSW_STCTL_SEC_STATUS) ||
- (p_ch->irb->scsw.cmd.stctl ==
- SCSW_STCTL_STATUS_PEND) ||
- (p_ch->irb->scsw.cmd.stctl ==
- (SCSW_STCTL_ALERT_STATUS |
- SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"writeUE");
- return;
- }
- clear_bit(0, (void *)&p_ch->IO_active);
- if (claw_test_and_setbit_busy(TB_TX,dev)==0) {
- claw_write_next(p_ch);
- claw_clearbit_busy(TB_TX,dev);
- claw_clear_busy(dev);
- }
- p_ch_r=(struct chbk *)&privptr->channel[READ];
- if (test_and_set_bit(CLAW_BH_ACTIVE,
- (void *)&p_ch_r->flag_a) == 0) {
- tasklet_schedule(&p_ch_r->tasklet);
- }
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: process CLAW_START_WRITE exit\n",
- dev->name);
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"StWtExit");
- return;
- default:
- printk(KERN_WARNING "%s: wrong selection code - irq "
- "state=%d\n",dev->name,p_ch->claw_state);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(2,trace,"badIRQ");
- return;
+ CLAW_DBF_TEXT(4, trace, "PCINoBH");
+ CLAW_DBF_TEXT(4, trace, "PCI_read");
+ return;
+ }
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "SPend_rd");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ claw_clearbit_busy(TB_RETRY, dev);
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0)
+ tasklet_schedule(&p_ch->tasklet);
+ else
+ CLAW_DBF_TEXT(4, trace, "RdBHAct");
+ CLAW_DBF_TEXT(4, trace, "RdIRQXit");
+ return;
+ case CLAW_START_WRITE:
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ printk(KERN_INFO "%s: Unit Check Occured in "
+ "write channel\n", dev->name);
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (p_ch->irb->ecw[0] & 0x80) {
+ printk(KERN_INFO "%s: Resetting Event "
+ "occurred:\n", dev->name);
+ init_timer(&p_ch->timer);
+ p_ch->timer.function =
+ (void *)claw_write_retry;
+ p_ch->timer.data = (unsigned long)p_ch;
+ p_ch->timer.expires = jiffies + 10*HZ;
+ add_timer(&p_ch->timer);
+ printk(KERN_INFO "%s: write connection "
+ "restarting\n", dev->name);
+ }
+ CLAW_DBF_TEXT(4, trace, "rstrtwrt");
+ return;
+ }
+ if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ printk(KERN_INFO "%s: Unit Exception "
+ "Occured in write channel\n",
+ dev->name);
+ }
+ if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.cmd.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+ CLAW_DBF_TEXT(4, trace, "writeUE");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (claw_test_and_setbit_busy(TB_TX, dev) == 0) {
+ claw_write_next(p_ch);
+ claw_clearbit_busy(TB_TX, dev);
+ claw_clear_busy(dev);
+ }
+ p_ch_r = (struct chbk *)&privptr->channel[READ];
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch_r->flag_a) == 0)
+ tasklet_schedule(&p_ch_r->tasklet);
+ CLAW_DBF_TEXT(4, trace, "StWtExit");
+ return;
+ default:
+ printk(KERN_WARNING "%s: wrong selection code - irq "
+ "state=%d\n", dev->name, p_ch->claw_state);
+ CLAW_DBF_TEXT(2, trace, "badIRQ");
+ return;
}
} /* end of claw_irq_handler */
@@ -1013,29 +779,11 @@ claw_irq_tasklet ( unsigned long data )
p_ch = (struct chbk *) data;
dev = (struct net_device *)p_ch->ndev;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"IRQtask");
-
+ CLAW_DBF_TEXT(4, trace, "IRQtask");
privptr = (struct claw_privbk *) dev->priv;
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: bh routine - state-%02x\n" ,
- dev->name, p_ch->claw_state);
-#endif
-
unpack_read(dev);
clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a);
- CLAW_DBF_TEXT(4,trace,"TskletXt");
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
+ CLAW_DBF_TEXT(4, trace, "TskletXt");
return;
} /* end of claw_irq_bh */
@@ -1060,16 +808,7 @@ claw_release(struct net_device *dev)
privptr = (struct claw_privbk *) dev->priv;
if (!privptr)
return 0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"release");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "Priv Buffalloc %d\n",privptr->buffs_alloc);
- printk(KERN_INFO "Priv p_buff_ccw = %p\n",&privptr->p_buff_ccw);
-#endif
+ CLAW_DBF_TEXT(4, trace, "release");
privptr->release_pend=1;
claw_setbit_busy(TB_STOP,dev);
for ( i = 1; i >=0 ; i--) {
@@ -1101,19 +840,15 @@ claw_release(struct net_device *dev)
privptr->pk_skb = NULL;
}
if(privptr->buffs_alloc != 1) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"none2fre");
+ CLAW_DBF_TEXT(4, trace, "none2fre");
return 0;
}
- CLAW_DBF_TEXT(4,trace,"freebufs");
+ CLAW_DBF_TEXT(4, trace, "freebufs");
if (privptr->p_buff_ccw != NULL) {
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
}
- CLAW_DBF_TEXT(4,trace,"freeread");
+ CLAW_DBF_TEXT(4, trace, "freeread");
if (privptr->p_env->read_size < PAGE_SIZE) {
if (privptr->p_buff_read != NULL) {
free_pages((unsigned long)privptr->p_buff_read,
@@ -1129,7 +864,7 @@ claw_release(struct net_device *dev)
p_buf=p_buf->next;
}
}
- CLAW_DBF_TEXT(4,trace,"freewrit");
+ CLAW_DBF_TEXT(4, trace, "freewrit");
if (privptr->p_env->write_size < PAGE_SIZE ) {
free_pages((unsigned long)privptr->p_buff_write,
(int)pages_to_order_of_mag(privptr->p_buff_write_num));
@@ -1143,7 +878,7 @@ claw_release(struct net_device *dev)
p_buf=p_buf->next;
}
}
- CLAW_DBF_TEXT(4,trace,"clearptr");
+ CLAW_DBF_TEXT(4, trace, "clearptr");
privptr->buffs_alloc = 0;
privptr->p_buff_ccw=NULL;
privptr->p_buff_read=NULL;
@@ -1180,18 +915,12 @@ claw_release(struct net_device *dev)
dev->name,
privptr->channel[READ].last_dstat,
privptr->channel[WRITE].last_dstat);
- CLAW_DBF_TEXT(2,trace,"badclose");
+ CLAW_DBF_TEXT(2, trace, "badclose");
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rlsexit");
+ CLAW_DBF_TEXT(4, trace, "rlsexit");
return 0;
} /* end of claw_release */
-
-
/*-------------------------------------------------------------------*
* claw_write_retry *
* *
@@ -1203,32 +932,12 @@ claw_write_retry ( struct chbk *p_ch )
struct net_device *dev=p_ch->ndev;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
- printk(KERN_INFO "claw: variable p_ch =\n");
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"w_retry");
+ CLAW_DBF_TEXT(4, trace, "w_retry");
if (p_ch->claw_state == CLAW_STOP) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
}
-#ifdef DEBUGMSG
- printk( KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,
- __func__,
- p_ch->claw_state);
-#endif
claw_strt_out_IO( dev );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"rtry_xit");
+ CLAW_DBF_TEXT(4, trace, "rtry_xit");
return;
} /* end of claw_write_retry */
@@ -1247,12 +956,7 @@ claw_write_next ( struct chbk * p_ch )
struct sk_buff *pk_skb;
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__func__);
- printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"claw_wrt");
+ CLAW_DBF_TEXT(4, trace, "claw_wrt");
if (p_ch->claw_state == CLAW_STOP)
return;
dev = (struct net_device *) p_ch->ndev;
@@ -1272,11 +976,6 @@ claw_write_next ( struct chbk * p_ch )
if (privptr->p_write_active_first!=NULL) {
claw_strt_out_IO(dev);
}
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
} /* end of claw_write_next */
@@ -1288,22 +987,12 @@ claw_write_next ( struct chbk * p_ch )
static void
claw_timer ( struct chbk * p_ch )
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
- printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
- dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"timer");
+ CLAW_DBF_TEXT(4, trace, "timer");
p_ch->flag |= CLAW_TIMER;
wake_up(&p_ch->wait);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->ndev->name,__func__,__LINE__);
-#endif
return;
} /* end of claw_timer */
-
/*
*
* functions
@@ -1324,10 +1013,8 @@ pages_to_order_of_mag(int num_of_pages)
{
int order_of_mag=1; /* assume 2 pages */
int nump=2;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
-#endif
- CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+
+ CLAW_DBF_TEXT_(5, trace, "pages%d", num_of_pages);
if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */
/* 512 pages = 2Meg on 4k page systems */
if (num_of_pages >= 512) {return 9; }
@@ -1338,11 +1025,7 @@ pages_to_order_of_mag(int num_of_pages)
order_of_mag +=1;
}
if (order_of_mag > 9) { order_of_mag = 9; } /* I know it's paranoid */
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s Exit on line %d, order = %d\n",
- __func__,__LINE__, order_of_mag);
-#endif
- CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+ CLAW_DBF_TEXT_(5, trace, "mag%d", order_of_mag);
return order_of_mag;
}
@@ -1358,21 +1041,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
struct claw_privbk *privptr;
struct ccw1 temp_ccw;
struct endccw * p_end;
-#ifdef IOTRACE
- struct ccwbk* p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "dev\n");
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "p_first\n");
- dumpit((char *) p_first, sizeof(struct ccwbk));
- printk(KERN_INFO "p_last\n");
- dumpit((char *) p_last, sizeof(struct ccwbk));
-#endif
- CLAW_DBF_TEXT(4,trace,"addreads");
+ CLAW_DBF_TEXT(4, trace, "addreads");
privptr = dev->priv;
p_end = privptr->p_end_ccw;
@@ -1380,11 +1049,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
* to apend the running channel programs
*/
if ( p_first==NULL) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"addexit");
+ CLAW_DBF_TEXT(4, trace, "addexit");
return 0;
}
@@ -1411,21 +1076,11 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
}
if ( privptr-> p_read_active_first ==NULL ) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
- dev->name,__func__);
- printk(KERN_INFO "%s:%s Read active first/last changed \n",
- dev->name,__func__);
-#endif
privptr-> p_read_active_first= p_first; /* set new first */
privptr-> p_read_active_last = p_last; /* set new last */
}
else {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s Read in progress \n",
- dev->name,__func__);
-#endif
/* set up TIC ccw */
temp_ccw.cda= (__u32)__pa(&p_first->read);
temp_ccw.count=0;
@@ -1462,27 +1117,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
privptr->p_read_active_last->next = p_first;
privptr->p_read_active_last=p_last;
} /* end of if ( privptr-> p_read_active_first ==NULL) */
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__func__);
- dumpit((char *)p_last, sizeof(struct ccwbk));
- printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__func__);
- dumpit((char *)p_end, sizeof(struct endccw));
-
- printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
- dumpit((char *)p_first, sizeof(struct ccwbk));
- printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
- dev->name,__func__);
- p_buf=privptr->p_read_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"addexit");
+ CLAW_DBF_TEXT(4, trace, "addexit");
return 0;
} /* end of add_claw_reads */
@@ -1494,44 +1129,29 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
static void
ccw_check_return_code(struct ccw_device *cdev, int return_code)
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter \n",
- cdev->dev.bus_id,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"ccwret");
-#ifdef DEBUGMSG
- printk(KERN_INFO "variable cdev =\n");
- dumpit((char *) cdev, sizeof(struct ccw_device));
- printk(KERN_INFO "variable return_code = %d\n",return_code);
-#endif
+ CLAW_DBF_TEXT(4, trace, "ccwret");
if (return_code != 0) {
switch (return_code) {
- case -EBUSY:
- printk(KERN_INFO "%s: Busy !\n",
- cdev->dev.bus_id);
- break;
- case -ENODEV:
- printk(KERN_EMERG "%s: Missing device called "
- "for IO ENODEV\n", cdev->dev.bus_id);
- break;
- case -EIO:
- printk(KERN_EMERG "%s: Status pending... EIO \n",
- cdev->dev.bus_id);
- break;
- case -EINVAL:
- printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
- cdev->dev.bus_id);
- break;
- default:
- printk(KERN_EMERG "%s: Unknown error in "
+ case -EBUSY: /* BUSY is a transient state no action needed */
+ break;
+ case -ENODEV:
+ printk(KERN_EMERG "%s: Missing device called "
+ "for IO ENODEV\n", cdev->dev.bus_id);
+ break;
+ case -EIO:
+ printk(KERN_EMERG "%s: Status pending... EIO \n",
+ cdev->dev.bus_id);
+ break;
+ case -EINVAL:
+ printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
+ cdev->dev.bus_id);
+ break;
+ default:
+ printk(KERN_EMERG "%s: Unknown error in "
"Do_IO %d\n",cdev->dev.bus_id, return_code);
- }
- }
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d\n",
- cdev->dev.bus_id,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"ccwret");
+ }
+ }
+ CLAW_DBF_TEXT(4, trace, "ccwret");
} /* end of ccw_check_return_code */
/*-------------------------------------------------------------------*
@@ -1541,173 +1161,46 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
static void
ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
{
- struct net_device *dev = p_ch->ndev;
-
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *)dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable sense =\n",dev->name);
- dumpit((char *)&sense, 2);
-#endif
- CLAW_DBF_TEXT(4,trace,"unitchek");
+ struct net_device *ndev = p_ch->ndev;
+ CLAW_DBF_TEXT(4, trace, "unitchek");
printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n",
- dev->name, sense);
+ ndev->name, sense);
if (sense & 0x40) {
if (sense & 0x01) {
printk(KERN_WARNING "%s: Interface disconnect or "
"Selective reset "
- "occurred (remote side)\n", dev->name);
+ "occurred (remote side)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: System reset occured"
- " (remote side)\n", dev->name);
+ " (remote side)\n", ndev->name);
}
}
else if (sense & 0x20) {
if (sense & 0x04) {
printk(KERN_WARNING "%s: Data-streaming "
- "timeout)\n", dev->name);
+ "timeout)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: Data-transfer parity"
- " error\n", dev->name);
+ " error\n", ndev->name);
}
}
else if (sense & 0x10) {
if (sense & 0x20) {
printk(KERN_WARNING "%s: Hardware malfunction "
- "(remote side)\n", dev->name);
+ "(remote side)\n", ndev->name);
}
else {
printk(KERN_WARNING "%s: read-data parity error "
- "(remote side)\n", dev->name);
+ "(remote side)\n", ndev->name);
}
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
} /* end of ccw_check_unit_check */
-
-
-/*-------------------------------------------------------------------*
-* Dump buffer format *
-* *
-*--------------------------------------------------------------------*/
-#ifdef DEBUG
-static void
-dumpit(char* buf, int len)
-{
-
- __u32 ct, sw, rm, dup;
- char *ptr, *rptr;
- char tbuf[82], tdup[82];
-#if (CONFIG_64BIT)
- char addr[22];
-#else
- char addr[12];
-#endif
- char boff[12];
- char bhex[82], duphex[82];
- char basc[40];
-
- sw = 0;
- rptr =ptr=buf;
- rm = 16;
- duphex[0] = 0x00;
- dup = 0;
- for ( ct=0; ct < len; ct++, ptr++, rptr++ ) {
- if (sw == 0) {
-#if (CONFIG_64BIT)
- sprintf(addr, "%16.16lX",(unsigned long)rptr);
-#else
- sprintf(addr, "%8.8X",(__u32)rptr);
-#endif
- sprintf(boff, "%4.4X", (__u32)ct);
- bhex[0] = '\0';
- basc[0] = '\0';
- }
- if ((sw == 4) || (sw == 12)) {
- strcat(bhex, " ");
- }
- if (sw == 8) {
- strcat(bhex, " ");
- }
-#if (CONFIG_64BIT)
- sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
-#else
- sprintf(tbuf,"%2.2X", (__u32)*ptr);
-#endif
- tbuf[2] = '\0';
- strcat(bhex, tbuf);
- if ((0!=isprint(*ptr)) && (*ptr >= 0x20)) {
- basc[sw] = *ptr;
- }
- else {
- basc[sw] = '.';
- }
- basc[sw+1] = '\0';
- sw++;
- rm--;
- if (sw==16) {
- if ((strcmp(duphex, bhex)) !=0) {
- if (dup !=0) {
- sprintf(tdup,"Duplicate as above to"
- " %s", addr);
- printk( KERN_INFO " "
- " --- %s ---\n",tdup);
- }
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- dup = 0;
- strcpy(duphex, bhex);
- }
- else {
- dup++;
- }
- sw = 0;
- rm = 16;
- }
- } /* endfor */
-
- if (sw != 0) {
- for ( ; rm > 0; rm--, sw++ ) {
- if ((sw==4) || (sw==12)) strcat(bhex, " ");
- if (sw==8) strcat(bhex, " ");
- strcat(bhex, " ");
- strcat(basc, " ");
- }
- if (dup !=0) {
- sprintf(tdup,"Duplicate as above to %s", addr);
- printk( KERN_INFO " --- %s ---\n",
- tdup);
- }
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- }
- else {
- if (dup >=1) {
- sprintf(tdup,"Duplicate as above to %s", addr);
- printk( KERN_INFO " --- %s ---\n",
- tdup);
- }
- if (dup !=0) {
- printk( KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
- }
- }
- return;
-
-} /* end of dumpit */
-#endif
-
/*-------------------------------------------------------------------*
* find_link *
*--------------------------------------------------------------------*/
@@ -1718,16 +1211,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
struct claw_env *p_env;
int rc=0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"findlink");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev = \n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable host_name = %s\n",dev->name, host_name);
- printk(KERN_INFO "%s: variable ws_name = %s\n",dev->name, ws_name);
-#endif
+ CLAW_DBF_TEXT(2, setup, "findlink");
privptr=dev->priv;
p_env=privptr->p_env;
switch (p_env->packing)
@@ -1750,10 +1234,6 @@ find_link(struct net_device *dev, char *host_name, char *ws_name )
break;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return 0;
} /* end of find_link */
@@ -1782,27 +1262,11 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
int lock;
struct clawph *pk_head;
struct chbk *ch;
-#ifdef IOTRACE
- struct ccwbk *p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"hw_tx");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev skb =\n",dev->name);
- dumpit((char *) skb, sizeof(struct sk_buff));
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable linkid = %ld\n",dev->name,linkid);
-#endif
+
+ CLAW_DBF_TEXT(4, trace, "hw_tx");
privptr = (struct claw_privbk *) (dev->priv);
p_ch=(struct chbk *)&privptr->channel[WRITE];
p_env =privptr->p_env;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__func__);
- dumpit((char *)skb ,sizeof(struct sk_buff));
-#endif
claw_free_wrt_buf(dev); /* Clean up free chain if posible */
/* scan the write queue to free any completed write packets */
p_first_ccw=NULL;
@@ -1834,11 +1298,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
claw_strt_out_IO(dev );
claw_free_wrt_buf( dev );
if (privptr->write_free_count==0) {
-#ifdef IOTRACE
- printk(KERN_INFO "%s: "
- "(claw_check_busy) no free write "
- "buffers\n", dev->name);
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
@@ -1851,10 +1310,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
/* tx lock */
if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: busy (claw_test_and_setbit_"
- "busy)\n", dev->name);
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
@@ -1871,28 +1326,16 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
privptr->p_write_free_chain == NULL ) {
claw_setbit_busy(TB_NOBUFFER,dev);
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: busy (claw_setbit_busy"
- "(TB_NOBUFFER))\n", dev->name);
- printk(KERN_INFO " free_count: %d, numBuffers : %d\n",
- (int)privptr->write_free_count,(int) numBuffers );
-#endif
ch = &privptr->channel[WRITE];
atomic_inc(&skb->users);
skb_queue_tail(&ch->collect_queue, skb);
- CLAW_DBF_TEXT(2,trace,"clawbusy");
+ CLAW_DBF_TEXT(2, trace, "clawbusy");
goto Done2;
}
pDataAddress=skb->data;
len_of_data=skb->len;
while (len_of_data > 0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
- dev->name ,__func__,len_of_data);
- dumpit((char *)pDataAddress ,64);
-#endif
p_this_ccw=privptr->p_write_free_chain; /* get a block */
if (p_this_ccw == NULL) { /* lost the race */
ch = &privptr->channel[WRITE];
@@ -1924,12 +1367,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
(__u32)__pa(&p_this_ccw->write);
}
p_last_ccw=p_this_ccw; /* save new last block */
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
- dev->name,__func__,bytesInThisBuffer);
- dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
- dumpit((char *)p_this_ccw->p_buffer, 64);
-#endif
}
/* FirstCCW and LastCCW now contain a new set of write channel
@@ -1962,13 +1399,11 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
pEnd->write1_nop2.count=1;
} /* end if if (pEnd->write1) */
-
if (privptr->p_write_active_first==NULL ) {
privptr->p_write_active_first=p_first_ccw;
privptr->p_write_active_last=p_last_ccw;
}
else {
-
/* set up Tic CCWs */
tempCCW.cda=(__u32)__pa(&p_first_ccw->write);
@@ -2007,19 +1442,6 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
} /* endif (p_first_ccw!=NULL) */
-
-
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() > Dump Active CCW chain \n",
- dev->name,__func__);
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
dev_kfree_skb_any(skb);
if (linkid==0) {
lock=LOCK_NO;
@@ -2029,21 +1451,12 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
}
claw_strt_out_IO(dev );
/* if write free count is zero , set NOBUFFER */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > free_count is %d\n",
- dev->name,__func__,
- (int) privptr->write_free_count );
-#endif
if (privptr->write_free_count==0) {
claw_setbit_busy(TB_NOBUFFER,dev);
}
Done2:
claw_clearbit_busy(TB_TX,dev);
Done:
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
- dev->name,__func__,__LINE__, rc);
-#endif
return(rc);
} /* end of claw_hw_tx */
@@ -2075,14 +1488,7 @@ init_ccw_bk(struct net_device *dev)
struct clawh *pClawH=NULL;
addr_t real_TIC_address;
int i,j;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"init_ccw");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(4, trace, "init_ccw");
/* initialize statistics field */
privptr->active_link_ID=0;
@@ -2107,20 +1513,6 @@ init_ccw_bk(struct net_device *dev)
*/
ccw_blocks_required =
privptr->p_env->read_buffers+privptr->p_env->write_buffers+1;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "ccw_blocks_required=%d\n",
- dev->name,__func__,
- ccw_blocks_required);
- printk(KERN_INFO "%s: %s() "
- "PAGE_SIZE=0x%x\n",
- dev->name,__func__,
- (unsigned int)PAGE_SIZE);
- printk(KERN_INFO "%s: %s() > "
- "PAGE_MASK=0x%x\n",
- dev->name,__func__,
- (unsigned int)PAGE_MASK);
-#endif
/*
* compute number of CCW blocks that will fit in a page
*/
@@ -2128,14 +1520,6 @@ init_ccw_bk(struct net_device *dev)
ccw_pages_required=
DIV_ROUND_UP(ccw_blocks_required, ccw_blocks_perpage);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
- dev->name,__func__,
- ccw_blocks_perpage);
- printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
- dev->name,__func__,
- ccw_pages_required);
-#endif
/*
* read and write sizes are set by 2 constants in claw.h
* 4k and 32k. Unpacked values other than 4k are not going to
@@ -2166,36 +1550,6 @@ init_ccw_bk(struct net_device *dev)
claw_write_pages = privptr->p_env->write_buffers *
privptr->p_buff_pages_perwrite;
}
-#ifdef DEBUGMSG
- if (privptr->p_env->read_size < PAGE_SIZE) {
- printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
- dev->name,__func__,
- claw_reads_perpage);
- }
- else {
- printk(KERN_INFO "%s: %s() pages_perread=%d\n",
- dev->name,__func__,
- privptr->p_buff_pages_perread);
- }
- printk(KERN_INFO "%s: %s() read_pages=%d\n",
- dev->name,__func__,
- claw_read_pages);
- if (privptr->p_env->write_size < PAGE_SIZE) {
- printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
- dev->name,__func__,
- claw_writes_perpage);
- }
- else {
- printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
- dev->name,__func__,
- privptr->p_buff_pages_perwrite);
- }
- printk(KERN_INFO "%s: %s() write_pages=%d\n",
- dev->name,__func__,
- claw_write_pages);
-#endif
-
-
/*
* allocate ccw_pages_required
*/
@@ -2204,17 +1558,6 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(ccw_pages_required ));
if (privptr->p_buff_ccw==NULL) {
- printk(KERN_INFO "%s: %s() "
- "__get_free_pages for CCWs failed : "
- "pages is %d\n",
- dev->name,__func__,
- ccw_pages_required );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > "
- "exit on line %d, rc = ENOMEM\n",
- dev->name,__func__,
- __LINE__);
-#endif
return -ENOMEM;
}
privptr->p_buff_ccw_num=ccw_pages_required;
@@ -2229,11 +1572,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_end_ccw = (struct endccw *)&privptr->end_ccw;
real_address = (__u32)__pa(privptr->p_end_ccw);
/* Initialize ending CCW block */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
- dev->name,__func__);
-#endif
-
p_endccw=privptr->p_end_ccw;
p_endccw->real=real_address;
p_endccw->write1=0x00;
@@ -2287,21 +1625,10 @@ init_ccw_bk(struct net_device *dev)
p_endccw->read2_nop2.count = 1;
p_endccw->read2_nop2.cda = 0;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
- dev->name,__func__);
- dumpit((char *)p_endccw, sizeof(struct endccw));
-#endif
-
/*
* Build a chain of CCWs
*
*/
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build a chain of CCW buffer \n",
- dev->name,__func__);
-#endif
p_buff=privptr->p_buff_ccw;
p_free_chain=NULL;
@@ -2316,26 +1643,10 @@ init_ccw_bk(struct net_device *dev)
}
p_buff+=PAGE_SIZE;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "End build a chain of CCW buffer \n",
- dev->name,__func__);
- p_buf=p_free_chain;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
-
/*
* Initialize ClawSignalBlock
*
*/
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() "
- "Begin initialize ClawSignalBlock \n",
- dev->name,__func__);
-#endif
if (privptr->p_claw_signal_blk==NULL) {
privptr->p_claw_signal_blk=p_free_chain;
p_free_chain=p_free_chain->next;
@@ -2344,12 +1655,6 @@ init_ccw_bk(struct net_device *dev)
pClawH->opcode=0xff;
pClawH->flag=CLAW_BUSY;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > End initialize "
- "ClawSignalBlock\n",
- dev->name,__func__);
- dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
-#endif
/*
* allocate write_pages_required and add to free chain
@@ -2360,17 +1665,7 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(claw_write_pages ));
if (privptr->p_buff_write==NULL) {
- printk(KERN_INFO "%s: %s() __get_free_pages for write"
- " bufs failed : get is for %d pages\n",
- dev->name,__func__,claw_write_pages );
- free_pages((unsigned long)privptr->p_buff_ccw,
- (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
privptr->p_buff_ccw=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d,"
- "rc = ENOMEM\n",
- dev->name,__func__,__LINE__);
-#endif
return -ENOMEM;
}
/*
@@ -2380,10 +1675,6 @@ init_ccw_bk(struct net_device *dev)
memset(privptr->p_buff_write, 0x00,
ccw_pages_required * PAGE_SIZE);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw write free "
- "chain \n",dev->name,__func__);
-#endif
privptr->p_write_free_chain=NULL;
p_buff=privptr->p_buff_write;
@@ -2419,18 +1710,7 @@ init_ccw_bk(struct net_device *dev)
p_buff=(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(
privptr->p_buff_pages_perwrite) );
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s __get_free_pages "
- "for writes buf: get for %d pages\n",
- dev->name,__func__,
- privptr->p_buff_pages_perwrite);
-#endif
if (p_buff==NULL) {
- printk(KERN_INFO "%s:%s __get_free_pages "
- "for writes buf failed : get is for %d pages\n",
- dev->name,
- __func__,
- privptr->p_buff_pages_perwrite );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
privptr->p_buff_ccw_num));
@@ -2443,12 +1723,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_buff_pages_perwrite));
p_buf=p_buf->next;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
- dev->name,
- __func__,
- __LINE__);
-#endif
return -ENOMEM;
} /* Error on get_pages */
memset(p_buff, 0x00, privptr->p_env->write_size );
@@ -2477,15 +1751,6 @@ init_ccw_bk(struct net_device *dev)
privptr->write_free_count=privptr->p_env->write_buffers;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s End build claw write free chain \n",
- dev->name,__func__);
- p_buf=privptr->p_write_free_chain;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-#endif
/*
* allocate read_pages_required and chain to free chain
*/
@@ -2495,10 +1760,6 @@ init_ccw_bk(struct net_device *dev)
(void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(claw_read_pages) );
if (privptr->p_buff_read==NULL) {
- printk(KERN_INFO "%s: %s() "
- "__get_free_pages for read buf failed : "
- "get is for %d pages\n",
- dev->name,__func__,claw_read_pages );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(
privptr->p_buff_ccw_num));
@@ -2508,10 +1769,6 @@ init_ccw_bk(struct net_device *dev)
privptr->p_buff_write_num));
privptr->p_buff_ccw=NULL;
privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
- " ENOMEM\n",dev->name,__func__,__LINE__);
-#endif
return -ENOMEM;
}
memset(privptr->p_buff_read, 0x00, claw_read_pages * PAGE_SIZE);
@@ -2520,10 +1777,6 @@ init_ccw_bk(struct net_device *dev)
* Build CLAW read free chain
*
*/
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__func__);
-#endif
p_buff=privptr->p_buff_read;
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
p_buf = p_free_chain;
@@ -2600,19 +1853,10 @@ init_ccw_bk(struct net_device *dev)
} /* for read_buffers */
} /* read_size < PAGE_SIZE */
else { /* read Size >= PAGE_SIZE */
-
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
- dev->name,__func__);
-#endif
for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
p_buff = (void *)__get_free_pages(__GFP_DMA,
(int)pages_to_order_of_mag(privptr->p_buff_pages_perread) );
if (p_buff==NULL) {
- printk(KERN_INFO "%s: %s() __get_free_pages for read "
- "buf failed : get is for %d pages\n",
- dev->name,__func__,
- privptr->p_buff_pages_perread );
free_pages((unsigned long)privptr->p_buff_ccw,
(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
/* free the write pages */
@@ -2633,11 +1877,6 @@ init_ccw_bk(struct net_device *dev)
}
privptr->p_buff_ccw=NULL;
privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
- dev->name,__func__,
- __LINE__);
-#endif
return -ENOMEM;
}
memset(p_buff, 0x00, privptr->p_env->read_size);
@@ -2706,22 +1945,9 @@ init_ccw_bk(struct net_device *dev)
} /* For read_buffers */
} /* read_size >= PAGE_SIZE */
} /* pBuffread = NULL */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() > End build claw read free chain \n",
- dev->name,__func__);
- p_buf=p_first_CCWB;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
-
-#endif
add_claw_reads( dev ,p_first_CCWB , p_last_CCWB);
privptr->buffs_alloc = 1;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
+
return 0;
} /* end of init_ccw_bk */
@@ -2735,14 +1961,8 @@ static void
probe_error( struct ccwgroup_device *cgdev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s enter \n",__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"proberr");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s variable cgdev =\n",__func__);
- dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
-#endif
+
+ CLAW_DBF_TEXT(4, trace, "proberr");
privptr=(struct claw_privbk *)cgdev->dev.driver_data;
if (privptr!=NULL) {
kfree(privptr->p_env);
@@ -2752,16 +1972,9 @@ probe_error( struct ccwgroup_device *cgdev)
kfree(privptr);
privptr=NULL;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s > exit on line %d\n",
- __func__,__LINE__);
-#endif
-
return;
} /* probe_error */
-
-
/*-------------------------------------------------------------------*
* claw_process_control *
* *
@@ -2783,32 +1996,19 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
struct conncmd *p_connect=NULL;
int rc;
struct chbk *p_ch = NULL;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > enter \n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"clw_cntl");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ccw =\n",dev->name);
- dumpit((char *) p_ccw, sizeof(struct ccwbk *));
-#endif
+ struct device *tdev;
+ CLAW_DBF_TEXT(2, setup, "clw_cntl");
udelay(1000); /* Wait a ms for the control packets to
*catch up to each other */
privptr=dev->priv;
p_env=privptr->p_env;
+ tdev = &privptr->channel[READ].cdev->dev;
memcpy( &temp_host_name, p_env->host_name, 8);
memcpy( &temp_ws_name, p_env->adapter_name , 8);
printk(KERN_INFO "%s: CLAW device %.8s: "
"Received Control Packet\n",
dev->name, temp_ws_name);
if (privptr->release_pend==1) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() > "
- "exit on line %d, rc=0\n",
- dev->name,__func__,__LINE__);
-#endif
return 0;
}
p_buf=p_ccw->p_buffer;
@@ -2818,261 +2018,246 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
} else {
memcpy(p_ctlbk, p_buf, sizeof(struct clawctl));
}
-#ifdef IOTRACE
- printk(KERN_INFO "%s: dump claw control data inbound\n",dev->name);
- dumpit((char *)p_ctlbk, sizeof(struct clawctl));
-#endif
switch (p_ctlbk->command)
{
- case SYSTEM_VALIDATE_REQUEST:
- if (p_ctlbk->version!=CLAW_VERSION_ID) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_WRONG_VERSION );
- printk("%s: %d is wrong version id. "
- "Expected %d\n",
- dev->name, p_ctlbk->version,
- CLAW_VERSION_ID);
- }
- p_sysval=(struct sysval *)&(p_ctlbk->data);
- printk( "%s: Recv Sys Validate Request: "
- "Vers=%d,link_id=%d,Corr=%d,WS name=%."
- "8s,Host name=%.8s\n",
- dev->name, p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_sysval->WS_name,
- p_sysval->host_name);
- if (0!=memcmp(temp_host_name,p_sysval->host_name,8)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_NAME_MISMATCH );
- CLAW_DBF_TEXT(2,setup,"HSTBAD");
- CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->host_name);
- CLAW_DBF_TEXT_(2,setup,"%s",temp_host_name);
- printk(KERN_INFO "%s: Host name mismatch\n",
- dev->name);
- printk(KERN_INFO "%s: Received :%s: "
- "expected :%s: \n",
- dev->name,
- p_sysval->host_name,
- temp_host_name);
- }
- if (0!=memcmp(temp_ws_name,p_sysval->WS_name,8)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_NAME_MISMATCH );
- CLAW_DBF_TEXT(2,setup,"WSNBAD");
- CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->WS_name);
- CLAW_DBF_TEXT_(2,setup,"%s",temp_ws_name);
- printk(KERN_INFO "%s: WS name mismatch\n",
- dev->name);
- printk(KERN_INFO "%s: Received :%s: "
- "expected :%s: \n",
- dev->name,
- p_sysval->WS_name,
- temp_ws_name);
- }
- if (( p_sysval->write_frame_size < p_env->write_size) &&
- ( p_env->packing == 0)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_HOST_RCV_TOO_SMALL );
- printk(KERN_INFO "%s: host write size is too "
- "small\n", dev->name);
- CLAW_DBF_TEXT(2,setup,"wrtszbad");
- }
- if (( p_sysval->read_frame_size < p_env->read_size) &&
- ( p_env->packing == 0)) {
- claw_snd_sys_validate_rsp(dev, p_ctlbk,
- CLAW_RC_HOST_RCV_TOO_SMALL );
- printk(KERN_INFO "%s: host read size is too "
- "small\n", dev->name);
- CLAW_DBF_TEXT(2,setup,"rdsizbad");
- }
- claw_snd_sys_validate_rsp(dev, p_ctlbk, 0 );
- printk("%s: CLAW device %.8s: System validate"
- " completed.\n",dev->name, temp_ws_name);
- printk("%s: sys Validate Rsize:%d Wsize:%d\n",dev->name,
- p_sysval->read_frame_size,p_sysval->write_frame_size);
- privptr->system_validate_comp=1;
- if(strncmp(p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
- p_env->packing = PACKING_ASK;
- }
- claw_strt_conn_req(dev);
- break;
-
- case SYSTEM_VALIDATE_RESPONSE:
- p_sysval=(struct sysval *)&(p_ctlbk->data);
- printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
- "WS name=%.8s,Host name=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->correlator,
- p_ctlbk->rc,
- p_sysval->WS_name,
- p_sysval->host_name);
- switch (p_ctlbk->rc)
- {
- case 0:
- printk(KERN_INFO "%s: CLAW device "
- "%.8s: System validate "
- "completed.\n",
- dev->name, temp_ws_name);
- if (privptr->system_validate_comp == 0)
- claw_strt_conn_req(dev);
- privptr->system_validate_comp=1;
- break;
- case CLAW_RC_NAME_MISMATCH:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : Host, WS name is "
- "mismatch\n",
- dev->name);
- break;
- case CLAW_RC_WRONG_VERSION:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : Wrong version\n",
- dev->name);
- break;
- case CLAW_RC_HOST_RCV_TOO_SMALL:
- printk(KERN_INFO "%s: Sys Validate "
- "Resp : bad frame size\n",
- dev->name);
- break;
- default:
- printk(KERN_INFO "%s: Sys Validate "
- "error code=%d \n",
- dev->name, p_ctlbk->rc );
- break;
- }
- break;
+ case SYSTEM_VALIDATE_REQUEST:
+ if (p_ctlbk->version != CLAW_VERSION_ID) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_WRONG_VERSION);
+ printk("%s: %d is wrong version id. "
+ "Expected %d\n",
+ dev->name, p_ctlbk->version,
+ CLAW_VERSION_ID);
+ }
+ p_sysval = (struct sysval *)&(p_ctlbk->data);
+ printk("%s: Recv Sys Validate Request: "
+ "Vers=%d,link_id=%d,Corr=%d,WS name=%."
+ "8s,Host name=%.8s\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ if (memcmp(temp_host_name, p_sysval->host_name, 8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH);
+ CLAW_DBF_TEXT(2, setup, "HSTBAD");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->host_name);
+ CLAW_DBF_TEXT_(2, setup, "%s", temp_host_name);
+ printk(KERN_INFO "%s: Host name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->host_name,
+ temp_host_name);
+ }
+ if (memcmp(temp_ws_name, p_sysval->WS_name, 8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH);
+ CLAW_DBF_TEXT(2, setup, "WSNBAD");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->WS_name);
+ CLAW_DBF_TEXT_(2, setup, "%s", temp_ws_name);
+ printk(KERN_INFO "%s: WS name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->WS_name,
+ temp_ws_name);
+ }
+ if ((p_sysval->write_frame_size < p_env->write_size) &&
+ (p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL);
+ printk(KERN_INFO "%s: host write size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2, setup, "wrtszbad");
+ }
+ if ((p_sysval->read_frame_size < p_env->read_size) &&
+ (p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL);
+ printk(KERN_INFO "%s: host read size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2, setup, "rdsizbad");
+ }
+ claw_snd_sys_validate_rsp(dev, p_ctlbk, 0);
+ printk(KERN_INFO "%s: CLAW device %.8s: System validate "
+ "completed.\n", dev->name, temp_ws_name);
+ printk("%s: sys Validate Rsize:%d Wsize:%d\n", dev->name,
+ p_sysval->read_frame_size, p_sysval->write_frame_size);
+ privptr->system_validate_comp = 1;
+ if (strncmp(p_env->api_type, WS_APPL_NAME_PACKED, 6) == 0)
+ p_env->packing = PACKING_ASK;
+ claw_strt_conn_req(dev);
+ break;
+ case SYSTEM_VALIDATE_RESPONSE:
+ p_sysval = (struct sysval *)&(p_ctlbk->data);
+ printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
+ "WS name=%.8s,Host name=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ switch (p_ctlbk->rc) {
+ case 0:
+ printk(KERN_INFO "%s: CLAW device "
+ "%.8s: System validate "
+ "completed.\n",
+ dev->name, temp_ws_name);
+ if (privptr->system_validate_comp == 0)
+ claw_strt_conn_req(dev);
+ privptr->system_validate_comp = 1;
+ break;
+ case CLAW_RC_NAME_MISMATCH:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Host, WS name is "
+ "mismatch\n",
+ dev->name);
+ break;
+ case CLAW_RC_WRONG_VERSION:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Wrong version\n",
+ dev->name);
+ break;
+ case CLAW_RC_HOST_RCV_TOO_SMALL:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : bad frame size\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Sys Validate "
+ "error code=%d \n",
+ dev->name, p_ctlbk->rc);
+ break;
+ }
+ break;
- case CONNECTION_REQUEST:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
- "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_connect->host_name,
- p_connect->WS_name);
- if (privptr->active_link_ID!=0 ) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "already logical link is active \n",
- dev->name);
- }
- if (p_ctlbk->linkid!=1 ) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "req logical link id is not 1\n",
+ case CONNECTION_REQUEST:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
+ "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (privptr->active_link_ID != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "already logical link is active \n",
+ dev->name);
+ }
+ if (p_ctlbk->linkid != 1) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "req logical link id is not 1\n",
+ dev->name);
+ }
+ rc = find_link(dev, p_connect->host_name, p_connect->WS_name);
+ if (rc != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Resp error: "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ claw_send_control(dev,
+ CONNECTION_CONFIRM, p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ 0, p_connect->host_name,
+ p_connect->WS_name);
+ if (p_env->packing == PACKING_ASK) {
+ p_env->packing = PACK_SEND;
+ claw_snd_conn_req(dev, 0);
+ }
+ printk(KERN_INFO "%s: CLAW device %.8s: Connection "
+ "completed link_id=%d.\n",
+ dev->name, temp_ws_name,
+ p_ctlbk->linkid);
+ privptr->active_link_ID = p_ctlbk->linkid;
+ p_ch = &privptr->channel[WRITE];
+ wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */
+ break;
+ case CONNECTION_RESPONSE:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
+ "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_connect->host_name,
+ p_connect->WS_name);
+
+ if (p_ctlbk->rc != 0) {
+ printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
+ dev->name, p_ctlbk->rc);
+ return 1;
+ }
+ rc = find_link(dev,
+ p_connect->host_name, p_connect->WS_name);
+ if (rc != 0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Resp error: "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ /* should be until CONNECTION_CONFIRM */
+ privptr->active_link_ID = -(p_ctlbk->linkid);
+ break;
+ case CONNECTION_CONFIRM:
+ p_connect = (struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
+ "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (p_ctlbk->linkid == -(privptr->active_link_ID)) {
+ privptr->active_link_ID = p_ctlbk->linkid;
+ if (p_env->packing > PACKING_ASK) {
+ printk(KERN_INFO "%s: Confirmed Now packing\n",
dev->name);
- }
- rc=find_link(dev,
- p_connect->host_name, p_connect->WS_name);
- if (rc!=0) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Req error : "
- "req appl name does not match\n",
- dev->name);
- }
- claw_send_control(dev,
- CONNECTION_CONFIRM, p_ctlbk->linkid,
- p_ctlbk->correlator,
- 0, p_connect->host_name,
- p_connect->WS_name);
- if (p_env->packing == PACKING_ASK) {
- printk("%s: Now Pack ask\n",dev->name);
- p_env->packing = PACK_SEND;
- claw_snd_conn_req(dev,0);
- }
- printk(KERN_INFO "%s: CLAW device %.8s: Connection "
- "completed link_id=%d.\n",
- dev->name, temp_ws_name,
- p_ctlbk->linkid);
- privptr->active_link_ID=p_ctlbk->linkid;
- p_ch=&privptr->channel[WRITE];
- wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */
- break;
- case CONNECTION_RESPONSE:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
- "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_ctlbk->rc,
- p_connect->host_name,
- p_connect->WS_name);
-
- if (p_ctlbk->rc !=0 ) {
- printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
- dev->name, p_ctlbk->rc);
- return 1;
- }
- rc=find_link(dev,
- p_connect->host_name, p_connect->WS_name);
- if (rc!=0) {
- claw_snd_disc(dev, p_ctlbk);
- printk(KERN_INFO "%s: Conn Resp error: "
- "req appl name does not match\n",
- dev->name);
- }
- /* should be until CONNECTION_CONFIRM */
- privptr->active_link_ID = - (p_ctlbk->linkid);
- break;
- case CONNECTION_CONFIRM:
- p_connect=(struct conncmd *)&(p_ctlbk->data);
- printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
- "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
- dev->name,
- p_ctlbk->version,
- p_ctlbk->linkid,
- p_ctlbk->correlator,
- p_connect->host_name,
- p_connect->WS_name);
- if (p_ctlbk->linkid== -(privptr->active_link_ID)) {
- privptr->active_link_ID=p_ctlbk->linkid;
- if (p_env->packing > PACKING_ASK) {
- printk(KERN_INFO "%s: Confirmed Now packing\n",dev->name);
- p_env->packing = DO_PACKED;
- }
- p_ch=&privptr->channel[WRITE];
- wake_up(&p_ch->wait);
- }
- else {
- printk(KERN_INFO "%s: Conn confirm: "
- "unexpected linkid=%d \n",
- dev->name, p_ctlbk->linkid);
- claw_snd_disc(dev, p_ctlbk);
- }
- break;
- case DISCONNECT:
- printk(KERN_INFO "%s: Disconnect: "
- "Vers=%d,link_id=%d,Corr=%d\n",
- dev->name, p_ctlbk->version,
- p_ctlbk->linkid, p_ctlbk->correlator);
- if ((p_ctlbk->linkid == 2) &&
- (p_env->packing == PACK_SEND)) {
- privptr->active_link_ID = 1;
p_env->packing = DO_PACKED;
}
- else
- privptr->active_link_ID=0;
- break;
- case CLAW_ERROR:
- printk(KERN_INFO "%s: CLAW ERROR detected\n",
- dev->name);
- break;
- default:
- printk(KERN_INFO "%s: Unexpected command code=%d \n",
- dev->name, p_ctlbk->command);
- break;
+ p_ch = &privptr->channel[WRITE];
+ wake_up(&p_ch->wait);
+ } else {
+ printk(KERN_INFO "%s: Conn confirm: "
+ "unexpected linkid=%d \n",
+ dev->name, p_ctlbk->linkid);
+ claw_snd_disc(dev, p_ctlbk);
+ }
+ break;
+ case DISCONNECT:
+ printk(KERN_INFO "%s: Disconnect: "
+ "Vers=%d,link_id=%d,Corr=%d\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid, p_ctlbk->correlator);
+ if ((p_ctlbk->linkid == 2) &&
+ (p_env->packing == PACK_SEND)) {
+ privptr->active_link_ID = 1;
+ p_env->packing = DO_PACKED;
+ } else
+ privptr->active_link_ID = 0;
+ break;
+ case CLAW_ERROR:
+ printk(KERN_INFO "%s: CLAW ERROR detected\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Unexpected command code=%d \n",
+ dev->name, p_ctlbk->command);
+ break;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
- dev->name,__func__,__LINE__);
-#endif
-
return 0;
} /* end of claw_process_control */
@@ -3092,18 +2277,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
struct conncmd *p_connect;
struct sk_buff *skb;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s > enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"sndcntl");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: Sending Control Packet \n",dev->name);
- printk(KERN_INFO "%s: variable type = 0x%X, link = "
- "%d, correlator = %d, rc = %d\n",
- dev->name,type, link, correlator, rc);
- printk(KERN_INFO "%s: variable local_name = %s, "
- "remote_name = %s\n",dev->name, local_name, remote_name);
-#endif
+ CLAW_DBF_TEXT(2, setup, "sndcntl");
privptr=dev->priv;
p_ctl=(struct clawctl *)&privptr->ctl_bk;
@@ -3125,7 +2299,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
p_sysval->read_frame_size=DEF_PACK_BUFSIZE;
p_sysval->write_frame_size=DEF_PACK_BUFSIZE;
} else {
- /* how big is the piggest group of packets */
+ /* how big is the biggest group of packets */
p_sysval->read_frame_size=privptr->p_env->read_size;
p_sysval->write_frame_size=privptr->p_env->write_size;
}
@@ -3155,29 +2329,14 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link,
skb = dev_alloc_skb(sizeof(struct clawctl));
if (!skb) {
- printk( "%s:%s low on mem, returning...\n",
- dev->name,__func__);
-#ifdef DEBUG
- printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
- dev->name,__func__);
-#endif
return -ENOMEM;
}
memcpy(skb_put(skb, sizeof(struct clawctl)),
p_ctl, sizeof(struct clawctl));
-#ifdef IOTRACE
- printk(KERN_INFO "%s: outbnd claw cntl data \n",dev->name);
- dumpit((char *)p_ctl,sizeof(struct clawctl));
-#endif
if (privptr->p_env->packing >= PACK_SEND)
claw_hw_tx(skb, dev, 1);
else
claw_hw_tx(skb, dev, 0);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
-
return 0;
} /* end of claw_send_control */
@@ -3192,22 +2351,11 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
struct claw_privbk *privptr=dev->priv;
struct clawctl *p_ctl;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"snd_conn");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable link = %X, dev =\n",dev->name, link);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(2, setup, "snd_conn");
rc = 1;
p_ctl=(struct clawctl *)&privptr->ctl_bk;
p_ctl->linkid = link;
if ( privptr->system_validate_comp==0x00 ) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
- dev->name,__func__,__LINE__);
-#endif
return rc;
}
if (privptr->p_env->packing == PACKING_ASK )
@@ -3220,10 +2368,6 @@ claw_snd_conn_req(struct net_device *dev, __u8 link)
if (privptr->p_env->packing == 0)
rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
HOST_APPL_NAME, privptr->p_env->api_type);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_conn_req */
@@ -3240,25 +2384,12 @@ claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
int rc;
struct conncmd * p_connect;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"snd_dsc");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ctl",dev->name);
- dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+ CLAW_DBF_TEXT(2, setup, "snd_dsc");
p_connect=(struct conncmd *)&p_ctl->data;
rc=claw_send_control(dev, DISCONNECT, p_ctl->linkid,
p_ctl->correlator, 0,
p_connect->host_name, p_connect->WS_name);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__, __LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_disc */
@@ -3276,18 +2407,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
struct claw_privbk *privptr;
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"chkresp");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable return_code = %d, dev =\n",
- dev->name, return_code);
- dumpit((char *) dev, sizeof(struct net_device));
- printk(KERN_INFO "%s: variable p_ctl =\n",dev->name);
- dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+ CLAW_DBF_TEXT(2, setup, "chkresp");
privptr = dev->priv;
p_env=privptr->p_env;
rc=claw_send_control(dev, SYSTEM_VALIDATE_RESPONSE,
@@ -3296,10 +2416,6 @@ claw_snd_sys_validate_rsp(struct net_device *dev,
return_code,
p_env->host_name,
p_env->adapter_name );
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_snd_sys_validate_rsp */
@@ -3313,19 +2429,8 @@ claw_strt_conn_req(struct net_device *dev )
{
int rc;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"conn_req");
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: variable dev =\n",dev->name);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
+ CLAW_DBF_TEXT(2, setup, "conn_req");
rc=claw_snd_conn_req(dev, 1);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
- dev->name,__func__,__LINE__, rc);
-#endif
return rc;
} /* end of claw_strt_conn_req */
@@ -3339,15 +2444,9 @@ static struct
net_device_stats *claw_stats(struct net_device *dev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"stats");
+
+ CLAW_DBF_TEXT(4, trace, "stats");
privptr = dev->priv;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return &privptr->stats;
} /* end of claw_stats */
@@ -3368,36 +2467,28 @@ unpack_read(struct net_device *dev )
struct clawph *p_packh;
void *p_packd;
struct clawctl *p_ctlrec=NULL;
+ struct device *p_dev;
__u32 len_of_data;
__u32 pack_off;
__u8 link_num;
__u8 mtc_this_frm=0;
__u32 bytes_to_mov;
- struct chbk *p_ch = NULL;
int i=0;
int p=0;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s enter \n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"unpkread");
+ CLAW_DBF_TEXT(4, trace, "unpkread");
p_first_ccw=NULL;
p_last_ccw=NULL;
p_packh=NULL;
p_packd=NULL;
privptr=dev->priv;
+
+ p_dev = &privptr->channel[READ].cdev->dev;
p_env = privptr->p_env;
p_this_ccw=privptr->p_read_active_first;
i=0;
while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) {
-#ifdef IOTRACE
- printk(KERN_INFO "%s p_this_ccw \n",dev->name);
- dumpit((char*)p_this_ccw, sizeof(struct ccwbk));
- printk(KERN_INFO "%s Inbound p_this_ccw->p_buffer(64)"
- " pk=%d \n",dev->name,p_env->packing);
- dumpit((char *)p_this_ccw->p_buffer, 64 );
-#endif
pack_off = 0;
p = 0;
p_this_ccw->header.flag=CLAW_PENDING;
@@ -3419,10 +2510,6 @@ unpack_read(struct net_device *dev )
else
link_num=p_this_ccw->header.opcode / 8;
if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s > More_to_come is ON\n",
- dev->name,__func__);
-#endif
mtc_this_frm=1;
if (p_this_ccw->header.length!=
privptr->p_env->read_size ) {
@@ -3445,22 +2532,12 @@ unpack_read(struct net_device *dev )
privptr->mtc_skipping=0; /* Ok, the end */
privptr->mtc_logical_link=-1;
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s goto next "
- "frame from MoretoComeSkip \n",
- dev->name,__func__);
-#endif
goto NextFrame;
}
if (link_num==0) {
claw_process_control(dev, p_this_ccw);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s goto next "
- "frame from claw_process_control \n",
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+ CLAW_DBF_TEXT(4, trace, "UnpkCntl");
goto NextFrame;
}
unpack_next:
@@ -3479,10 +2556,6 @@ unpack_next:
bytes_to_mov=p_this_ccw->header.length;
}
if (privptr->mtc_logical_link<0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s mtc_logical_link < 0 \n",
- dev->name,__func__);
-#endif
/*
* if More-To-Come is set in this frame then we don't know
@@ -3496,15 +2569,6 @@ unpack_next:
if (bytes_to_mov > (MAX_ENVELOPE_SIZE- privptr->mtc_offset) ) {
/* error */
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s > goto next "
- "frame from MoretoComeSkip \n",
- dev->name,
- __func__);
- printk(KERN_INFO " bytes_to_mov %d > (MAX_ENVELOPE_"
- "SIZE-privptr->mtc_offset %d)\n",
- bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
-#endif
privptr->stats.rx_frame_errors++;
goto NextFrame;
}
@@ -3516,16 +2580,6 @@ unpack_next:
memcpy( privptr->p_mtc_envelope+ privptr->mtc_offset,
p_this_ccw->p_buffer, bytes_to_mov);
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() received data \n",
- dev->name,__func__);
- if (p_env->packing == DO_PACKED)
- dumpit((char *)p_packd+sizeof(struct clawph),32);
- else
- dumpit((char *)p_this_ccw->p_buffer, 32);
- printk(KERN_INFO "%s: %s() bytelength %d \n",
- dev->name,__func__,bytes_to_mov);
-#endif
if (mtc_this_frm==0) {
len_of_data=privptr->mtc_offset+bytes_to_mov;
skb=dev_alloc_skb(len_of_data);
@@ -3540,11 +2594,6 @@ unpack_next:
privptr->stats.rx_packets++;
privptr->stats.rx_bytes+=len_of_data;
netif_rx(skb);
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: %s() netif_"
- "rx(skb) completed \n",
- dev->name,__func__);
-#endif
}
else {
privptr->stats.rx_dropped++;
@@ -3581,28 +2630,14 @@ NextFrame:
* chain to next block on active read queue
*/
p_this_ccw = privptr->p_read_active_first;
- CLAW_DBF_TEXT_(4,trace,"rxpkt %d",p);
+ CLAW_DBF_TEXT_(4, trace, "rxpkt %d", p);
} /* end of while */
/* check validity */
-#ifdef IOTRACE
- printk(KERN_INFO "%s:%s processed frame is %d \n",
- dev->name,__func__,i);
- printk(KERN_INFO "%s:%s F:%lx L:%lx\n",
- dev->name,
- __func__,
- (unsigned long)p_first_ccw,
- (unsigned long)p_last_ccw);
-#endif
- CLAW_DBF_TEXT_(4,trace,"rxfrm %d",i);
+ CLAW_DBF_TEXT_(4, trace, "rxfrm %d", i);
add_claw_reads(dev, p_first_ccw, p_last_ccw);
- p_ch=&privptr->channel[READ];
claw_strt_read(dev, LOCK_YES);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s: %s exit on line %d\n",
- dev->name, __func__, __LINE__);
-#endif
return;
} /* end of unpack_read */
@@ -3622,12 +2657,7 @@ claw_strt_read (struct net_device *dev, int lock )
struct clawh *p_clawh;
p_ch=&privptr->channel[READ];
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter \n",dev->name,__func__);
- printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
- dumpit((char *) dev, sizeof(struct net_device));
-#endif
- CLAW_DBF_TEXT(4,trace,"StRdNter");
+ CLAW_DBF_TEXT(4, trace, "StRdNter");
p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
p_clawh->flag=CLAW_IDLE; /* 0x00 */
@@ -3637,21 +2667,11 @@ claw_strt_read (struct net_device *dev, int lock )
privptr->p_read_active_first->header.flag!=CLAW_PENDING )) {
p_clawh->flag=CLAW_BUSY; /* 0xff */
}
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__func__, p_ch->claw_state);
-#endif
if (lock==LOCK_YES) {
spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
}
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: HOT READ started in %s\n" ,
- dev->name,__func__);
- p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
- dumpit((char *)&p_clawh->flag , 1);
-#endif
- CLAW_DBF_TEXT(4,trace,"HotRead");
+ CLAW_DBF_TEXT(4, trace, "HotRead");
p_ccwbk=privptr->p_read_active_first;
parm = (unsigned long) p_ch;
rc = ccw_device_start (p_ch->cdev, &p_ccwbk->read, parm,
@@ -3661,21 +2681,13 @@ claw_strt_read (struct net_device *dev, int lock )
}
}
else {
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
- dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,trace,"ReadAct");
+ CLAW_DBF_TEXT(2, trace, "ReadAct");
}
if (lock==LOCK_YES) {
spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
- CLAW_DBF_TEXT(4,trace,"StRdExit");
+ CLAW_DBF_TEXT(4, trace, "StRdExit");
return;
} /* end of claw_strt_read */
@@ -3693,38 +2705,23 @@ claw_strt_out_IO( struct net_device *dev )
struct chbk *p_ch;
struct ccwbk *p_first_ccw;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
if (!dev) {
return;
}
privptr=(struct claw_privbk *)dev->priv;
p_ch=&privptr->channel[WRITE];
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s state-%02x\n" ,
- dev->name,__func__,p_ch->claw_state);
-#endif
- CLAW_DBF_TEXT(4,trace,"strt_io");
+ CLAW_DBF_TEXT(4, trace, "strt_io");
p_first_ccw=privptr->p_write_active_first;
if (p_ch->claw_state == CLAW_STOP)
return;
if (p_first_ccw == NULL) {
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
return;
}
if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
parm = (unsigned long) p_ch;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
- dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
-#endif
- CLAW_DBF_TEXT(2,trace,"StWrtIO");
+ CLAW_DBF_TEXT(2, trace, "StWrtIO");
rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm,
0xff, 0);
if (rc != 0) {
@@ -3732,11 +2729,6 @@ claw_strt_out_IO( struct net_device *dev )
}
}
dev->trans_start = jiffies;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- dev->name,__func__,__LINE__);
-#endif
-
return;
} /* end of claw_strt_out_IO */
@@ -3754,32 +2746,11 @@ claw_free_wrt_buf( struct net_device *dev )
struct ccwbk*p_last_ccw;
struct ccwbk*p_this_ccw;
struct ccwbk*p_next_ccw;
-#ifdef IOTRACE
- struct ccwbk*p_buf;
-#endif
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
- printk(KERN_INFO "%s: free count = %d variable dev =\n",
- dev->name,privptr->write_free_count);
-#endif
- CLAW_DBF_TEXT(4,trace,"freewrtb");
+
+ CLAW_DBF_TEXT(4, trace, "freewrtb");
/* scan the write queue to free any completed write packets */
p_first_ccw=NULL;
p_last_ccw=NULL;
-#ifdef IOTRACE
- printk(KERN_INFO "%s: Dump current CCW chain \n",dev->name );
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
- }
- if (p_buf==NULL) {
- printk(KERN_INFO "%s: privptr->p_write_"
- "active_first==NULL\n",dev->name );
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
p_this_ccw=privptr->p_write_active_first;
while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING))
{
@@ -3809,31 +2780,8 @@ claw_free_wrt_buf( struct net_device *dev )
/* whole chain removed? */
if (privptr->p_write_active_first==NULL) {
privptr->p_write_active_last=NULL;
-#ifdef DEBUGMSG
- printk(KERN_INFO "%s:%s p_write_"
- "active_first==NULL\n",dev->name,__func__);
-#endif
- }
-#ifdef IOTRACE
- printk(KERN_INFO "%s: Dump arranged CCW chain \n",dev->name );
- p_buf=privptr->p_write_active_first;
- while (p_buf!=NULL) {
- dumpit((char *)p_buf, sizeof(struct ccwbk));
- p_buf=p_buf->next;
}
- if (p_buf==NULL) {
- printk(KERN_INFO "%s: privptr->p_write_active_"
- "first==NULL\n",dev->name );
- }
- p_buf=(struct ccwbk*)privptr->p_end_ccw;
- dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
-
- CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
- dev->name,__func__, __LINE__,privptr->write_free_count);
-#endif
+ CLAW_DBF_TEXT_(4, trace, "FWC=%d", privptr->write_free_count);
return;
}
@@ -3845,14 +2793,11 @@ static void
claw_free_netdevice(struct net_device * dev, int free_dev)
{
struct claw_privbk *privptr;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"free_dev");
+ CLAW_DBF_TEXT(2, setup, "free_dev");
if (!dev)
return;
- CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
privptr = dev->priv;
if (dev->flags & IFF_RUNNING)
claw_release(dev);
@@ -3865,10 +2810,7 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
free_netdev(dev);
}
#endif
- CLAW_DBF_TEXT(2,setup,"feee_ok");
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
+ CLAW_DBF_TEXT(2, setup, "free_ok");
}
/**
@@ -3879,17 +2821,8 @@ claw_free_netdevice(struct net_device * dev, int free_dev)
static void
claw_init_netdevice(struct net_device * dev)
{
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"init_dev");
- CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
- if (!dev) {
- printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
- __func__,__LINE__);
- CLAW_DBF_TEXT(2,setup,"baddev");
- return;
- }
+ CLAW_DBF_TEXT(2, setup, "init_dev");
+ CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
dev->mtu = CLAW_DEFAULT_MTU_SIZE;
dev->hard_start_xmit = claw_tx;
dev->open = claw_open;
@@ -3901,10 +2834,7 @@ claw_init_netdevice(struct net_device * dev)
dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 1300;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
- CLAW_DBF_TEXT(2,setup,"initok");
+ CLAW_DBF_TEXT(2, setup, "initok");
return;
}
@@ -3921,10 +2851,7 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
struct chbk *p_ch;
struct ccw_dev_id dev_id;
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
-#endif
- CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id);
privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
p_ch = &privptr->channel[i];
p_ch->cdev = cdev;
@@ -3932,18 +2859,8 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
ccw_device_get_id(cdev, &dev_id);
p_ch->devno = dev_id.devno;
if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
- printk(KERN_WARNING "%s Out of memory in %s for irb\n",
- p_ch->id,__func__);
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- p_ch->id,__func__,__LINE__);
-#endif
return -ENOMEM;
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "%s:%s Exit on line %d\n",
- cdev->dev.bus_id,__func__,__LINE__);
-#endif
return 0;
}
@@ -3965,9 +2882,8 @@ claw_new_device(struct ccwgroup_device *cgdev)
int ret;
struct ccw_dev_id dev_id;
- pr_debug("%s() called\n", __func__);
printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
- CLAW_DBF_TEXT(2,setup,"new_dev");
+ CLAW_DBF_TEXT(2, setup, "new_dev");
privptr = cgdev->dev.driver_data;
cgdev->cdev[READ]->dev.driver_data = privptr;
cgdev->cdev[WRITE]->dev.driver_data = privptr;
@@ -3982,22 +2898,21 @@ claw_new_device(struct ccwgroup_device *cgdev)
if (ret == 0)
ret = add_channel(cgdev->cdev[1],1,privptr);
if (ret != 0) {
- printk(KERN_WARNING
- "add channel failed "
- "with ret = %d\n", ret);
- goto out;
+ printk(KERN_WARNING
+ "add channel failed with ret = %d\n", ret);
+ goto out;
}
ret = ccw_device_set_online(cgdev->cdev[READ]);
if (ret != 0) {
printk(KERN_WARNING
- "claw: ccw_device_set_online %s READ failed "
+ "claw: ccw_device_set_online %s READ failed "
"with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
goto out;
}
ret = ccw_device_set_online(cgdev->cdev[WRITE]);
if (ret != 0) {
printk(KERN_WARNING
- "claw: ccw_device_set_online %s WRITE failed "
+ "claw: ccw_device_set_online %s WRITE failed "
"with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
goto out;
}
@@ -4014,18 +2929,16 @@ claw_new_device(struct ccwgroup_device *cgdev)
SET_NETDEV_DEV(dev, &cgdev->dev);
if (register_netdev(dev) != 0) {
claw_free_netdevice(dev, 1);
- CLAW_DBF_TEXT(2,trace,"regfail");
+ CLAW_DBF_TEXT(2, trace, "regfail");
goto out;
}
dev->flags &=~IFF_RUNNING;
if (privptr->buffs_alloc == 0) {
ret=init_ccw_bk(dev);
if (ret !=0) {
- printk(KERN_WARNING
- "claw: init_ccw_bk failed with ret=%d\n", ret);
unregister_netdev(dev);
claw_free_netdevice(dev,1);
- CLAW_DBF_TEXT(2,trace,"ccwmem");
+ CLAW_DBF_TEXT(2, trace, "ccwmem");
goto out;
}
}
@@ -4047,7 +2960,6 @@ claw_new_device(struct ccwgroup_device *cgdev)
out:
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
-
return -ENODEV;
}
@@ -4056,8 +2968,7 @@ claw_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
- CLAW_DBF_TEXT(4,trace,"purgque");
-
+ CLAW_DBF_TEXT(4, trace, "purgque");
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
dev_kfree_skb_any(skb);
@@ -4078,8 +2989,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev)
struct net_device *ndev;
int ret;
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
if (!priv)
return -ENODEV;
@@ -4108,13 +3018,10 @@ claw_remove_device(struct ccwgroup_device *cgdev)
{
struct claw_privbk *priv;
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ BUG_ON(!cgdev);
+ CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
priv = cgdev->dev.driver_data;
- if (!priv) {
- printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
- return;
- }
+ BUG_ON(!priv);
printk(KERN_INFO "claw: %s() called %s will be removed.\n",
__func__,cgdev->cdev[0]->dev.bus_id);
if (cgdev->state == CCWGROUP_ONLINE)
@@ -4133,6 +3040,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
cgdev->cdev[READ]->dev.driver_data = NULL;
cgdev->cdev[WRITE]->dev.driver_data = NULL;
put_device(&cgdev->dev);
+
+ return;
}
@@ -4168,8 +3077,8 @@ claw_hname_write(struct device *dev, struct device_attribute *attr, const char *
strncpy(p_env->host_name,buf, count);
p_env->host_name[count-1] = 0x20; /* clear extra 0x0a */
p_env->host_name[MAX_NAME_LEN] = 0x00;
- CLAW_DBF_TEXT(2,setup,"HstnSet");
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->host_name);
+ CLAW_DBF_TEXT(2, setup, "HstnSet");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->host_name);
return count;
}
@@ -4186,7 +3095,7 @@ claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf)
if (!priv)
return -ENODEV;
p_env = priv->p_env;
- return sprintf(buf, "%s\n",p_env->adapter_name);
+ return sprintf(buf, "%s\n", p_env->adapter_name);
}
static ssize_t
@@ -4205,8 +3114,8 @@ claw_adname_write(struct device *dev, struct device_attribute *attr, const char
strncpy(p_env->adapter_name,buf, count);
p_env->adapter_name[count-1] = 0x20; /* clear extra 0x0a */
p_env->adapter_name[MAX_NAME_LEN] = 0x00;
- CLAW_DBF_TEXT(2,setup,"AdnSet");
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->adapter_name);
+ CLAW_DBF_TEXT(2, setup, "AdnSet");
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->adapter_name);
return count;
}
@@ -4247,15 +3156,15 @@ claw_apname_write(struct device *dev, struct device_attribute *attr, const char
p_env->read_size=DEF_PACK_BUFSIZE;
p_env->write_size=DEF_PACK_BUFSIZE;
p_env->packing=PACKING_ASK;
- CLAW_DBF_TEXT(2,setup,"PACKING");
+ CLAW_DBF_TEXT(2, setup, "PACKING");
}
else {
p_env->packing=0;
p_env->read_size=CLAW_FRAME_SIZE;
p_env->write_size=CLAW_FRAME_SIZE;
- CLAW_DBF_TEXT(2,setup,"ApiSet");
+ CLAW_DBF_TEXT(2, setup, "ApiSet");
}
- CLAW_DBF_TEXT_(2,setup,"%s",p_env->api_type);
+ CLAW_DBF_TEXT_(2, setup, "%s", p_env->api_type);
return count;
}
@@ -4295,8 +3204,8 @@ claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *
if ((nnn > max ) || (nnn < 2))
return -EINVAL;
p_env->write_buffers = nnn;
- CLAW_DBF_TEXT(2,setup,"Wbufset");
- CLAW_DBF_TEXT_(2,setup,"WB=%d",p_env->write_buffers);
+ CLAW_DBF_TEXT(2, setup, "Wbufset");
+ CLAW_DBF_TEXT_(2, setup, "WB=%d", p_env->write_buffers);
return count;
}
@@ -4336,8 +3245,8 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *
if ((nnn > max ) || (nnn < 2))
return -EINVAL;
p_env->read_buffers = nnn;
- CLAW_DBF_TEXT(2,setup,"Rbufset");
- CLAW_DBF_TEXT_(2,setup,"RB=%d",p_env->read_buffers);
+ CLAW_DBF_TEXT(2, setup, "Rbufset");
+ CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
return count;
}
@@ -4359,16 +3268,14 @@ static struct attribute_group claw_attr_group = {
static int
claw_add_files(struct device *dev)
{
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT(2,setup,"add_file");
+ CLAW_DBF_TEXT(2, setup, "add_file");
return sysfs_create_group(&dev->kobj, &claw_attr_group);
}
static void
claw_remove_files(struct device *dev)
{
- pr_debug("%s() called\n", __func__);
- CLAW_DBF_TEXT(2,setup,"rem_file");
+ CLAW_DBF_TEXT(2, setup, "rem_file");
sysfs_remove_group(&dev->kobj, &claw_attr_group);
}
@@ -4397,35 +3304,27 @@ claw_init(void)
int ret = 0;
printk(KERN_INFO "claw: starting driver\n");
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() enter \n",__func__);
-#endif
ret = claw_register_debug_facility();
if (ret) {
printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
__func__,ret);
return ret;
}
- CLAW_DBF_TEXT(2,setup,"init_mod");
+ CLAW_DBF_TEXT(2, setup, "init_mod");
ret = register_cu3088_discipline(&claw_group_driver);
if (ret) {
+ CLAW_DBF_TEXT(2, setup, "init_bad");
claw_unregister_debug_facility();
printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
__func__,ret);
}
-#ifdef FUNCTRACE
- printk(KERN_INFO "claw: %s() exit \n",__func__);
-#endif
return ret;
}
module_init(claw_init);
module_exit(claw_cleanup);
-
-
-/*--------------------------------------------------------------------*
-* End of File *
-*---------------------------------------------------------------------*/
-
-
+MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
+MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \
+ "Copyright 2000,2008 IBM Corporation\n");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index 8eb25d00b2e..1ca58f15347 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -7,6 +7,7 @@
*/
#include <linux/stddef.h>
+#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
@@ -22,15 +23,13 @@
* Debug Facility Stuff
*/
-DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
- [CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, 5, NULL},
- [CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, 3, NULL},
- [CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, 3, NULL},
- [CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 64, 5, NULL},
- [CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 64, 3, NULL},
- [CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 64, 3, NULL},
+ [CTCM_DBF_SETUP] = {"ctc_setup", 8, 1, 64, CTC_DBF_INFO, NULL},
+ [CTCM_DBF_ERROR] = {"ctc_error", 8, 1, 64, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_TRACE] = {"ctc_trace", 8, 1, 64, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 80, CTC_DBF_INFO, NULL},
+ [CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 80, CTC_DBF_ERROR, NULL},
+ [CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 80, CTC_DBF_ERROR, NULL},
};
void ctcm_unregister_dbf_views(void)
@@ -65,3 +64,17 @@ int ctcm_register_dbf_views(void)
return 0;
}
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...)
+{
+ char dbf_txt_buf[64];
+ va_list args;
+
+ if (level > (ctcm_dbf[dbf_nix].id)->level)
+ return;
+ va_start(args, fmt);
+ vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
+ va_end(args);
+
+ debug_text_event(ctcm_dbf[dbf_nix].id, level, dbf_txt_buf);
+}
+
diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
index fdff34fe59a..26966d0b9ab 100644
--- a/drivers/s390/net/ctcm_dbug.h
+++ b/drivers/s390/net/ctcm_dbug.h
@@ -20,16 +20,17 @@
#else
#define do_debug 0
#endif
-#ifdef DEBUGDATA
- #define do_debug_data 1
-#else
- #define do_debug_data 0
-#endif
#ifdef DEBUGCCW
#define do_debug_ccw 1
+ #define DEBUGDATA 1
#else
#define do_debug_ccw 0
#endif
+#ifdef DEBUGDATA
+ #define do_debug_data 1
+#else
+ #define do_debug_data 0
+#endif
/* define dbf debug levels similar to kernel msg levels */
#define CTC_DBF_ALWAYS 0 /* always print this */
@@ -42,8 +43,6 @@
#define CTC_DBF_INFO 5 /* informational */
#define CTC_DBF_DEBUG 6 /* debug-level messages */
-DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
enum ctcm_dbf_names {
CTCM_DBF_SETUP,
CTCM_DBF_ERROR,
@@ -67,6 +66,7 @@ extern struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS];
int ctcm_register_dbf_views(void);
void ctcm_unregister_dbf_views(void);
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *text, ...);
static inline const char *strtail(const char *s, int n)
{
@@ -74,12 +74,6 @@ static inline const char *strtail(const char *s, int n)
return (l > n) ? s + (l - n) : s;
}
-/* sort out levels early to avoid unnecessary sprintfs */
-static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (dbf_grp->level >= level);
-}
-
#define CTCM_FUNTAIL strtail((char *)__func__, 16)
#define CTCM_DBF_TEXT(name, level, text) \
@@ -94,16 +88,7 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
} while (0)
#define CTCM_DBF_TEXT_(name, level, text...) \
- do { \
- if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
- char *ctcm_dbf_txt_buf = \
- get_cpu_var(ctcm_dbf_txt_buf); \
- sprintf(ctcm_dbf_txt_buf, text); \
- debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
- level, ctcm_dbf_txt_buf); \
- put_cpu_var(ctcm_dbf_txt_buf); \
- } \
- } while (0)
+ ctcm_dbf_longtext(CTCM_DBF_##name, level, text)
/*
* cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
@@ -112,13 +97,13 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
*/
#define CTCM_DBF_DEV_NAME(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
+ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) :- %s", \
CTCM_FUNTAIL, dev->name, text); \
} while (0)
#define MPC_DBF_DEV_NAME(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
+ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) := %s", \
CTCM_FUNTAIL, dev->name, text); \
} while (0)
@@ -137,13 +122,13 @@ static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
*/
#define CTCM_DBF_DEV(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
+ CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) :-: %s", \
CTCM_FUNTAIL, dev, text); \
} while (0)
#define MPC_DBF_DEV(cat, dev, text) \
do { \
- CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
+ CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) :=: %s", \
CTCM_FUNTAIL, dev, text); \
} while (0)
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
index 7e6bd387f4d..0b4e6253abe 100644
--- a/drivers/s390/net/ctcm_fsms.c
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -190,7 +190,8 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
{
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
- "ccw error %s (%s): %04x\n", ch->id, msg, rc);
+ "%s(%s): %s: %04x\n",
+ CTCM_FUNTAIL, ch->id, msg, rc);
switch (rc) {
case -EBUSY:
ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
@@ -212,7 +213,7 @@ void ctcm_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+ CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __func__);
while ((skb = skb_dequeue(q))) {
atomic_dec(&skb->users);
@@ -251,6 +252,8 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
unsigned long duration;
struct timespec done_stamp = current_kernel_time(); /* xtime */
+ CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
duration =
(done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
(done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
@@ -258,8 +261,9 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
ch->prof.tx_time = duration;
if (ch->irb->scsw.cmd.count != 0)
- ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
- dev->name, ch->irb->scsw.cmd.count);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): TX not complete, remaining %d bytes",
+ CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
fsm_deltimer(&ch->timer);
while ((skb = skb_dequeue(&ch->io_queue))) {
priv->stats.tx_packets++;
@@ -334,7 +338,8 @@ void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+ CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
fsm_deltimer(&ch->timer);
fsm_newstate(fi, CTC_STATE_TXIDLE);
fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
@@ -361,15 +366,17 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (len < 8) {
- ctcm_pr_debug("%s: got packet with length %d < 8\n",
- dev->name, len);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got packet with length %d < 8\n",
+ CTCM_FUNTAIL, dev->name, len);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto again;
}
if (len > ch->max_bufsize) {
- ctcm_pr_debug("%s: got packet with length %d > %d\n",
- dev->name, len, ch->max_bufsize);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got packet with length %d > %d\n",
+ CTCM_FUNTAIL, dev->name, len, ch->max_bufsize);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto again;
@@ -388,8 +395,9 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
break;
}
if ((len < block_len) || (len > check_len)) {
- ctcm_pr_debug("%s: got block length %d != rx length %d\n",
- dev->name, block_len, len);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s): got block length %d != rx length %d\n",
+ CTCM_FUNTAIL, dev->name, block_len, len);
if (do_debug)
ctcmpc_dump_skb(skb, 0);
@@ -425,17 +433,23 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
*/
static void chx_firstio(fsm_instance *fi, int event, void *arg)
{
- struct channel *ch = arg;
int rc;
+ struct channel *ch = arg;
+ int fsmstate = fsm_getstate(fi);
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) : %02x",
+ CTCM_FUNTAIL, ch->id, fsmstate);
- if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
- ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
+ ch->sense_rc = 0; /* reset unit check report control */
+ if (fsmstate == CTC_STATE_TXIDLE)
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): remote side issued READ?, init.\n",
+ CTCM_FUNTAIL, ch->id);
fsm_deltimer(&ch->timer);
if (ctcm_checkalloc_buffer(ch))
return;
- if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
+ if ((fsmstate == CTC_STATE_SETUPWAIT) &&
(ch->protocol == CTCM_PROTO_OS390)) {
/* OS/390 resp. z/OS */
if (CHANNEL_DIRECTION(ch->flags) == READ) {
@@ -451,7 +465,6 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg)
}
return;
}
-
/*
* Don't setup a timer for receiving the initial RX frame
* if in compatibility mode, since VM TCP delays the initial
@@ -505,11 +518,10 @@ static void chx_rxidle(fsm_instance *fi, int event, void *arg)
__u16 buflen;
int rc;
- CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
fsm_deltimer(&ch->timer);
buflen = *((__u16 *)ch->trans_skb->data);
- if (do_debug)
- ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+ CTCM_PR_DEBUG("%s: %s: Initial RX count = %d\n",
+ __func__, dev->name, buflen);
if (buflen >= CTCM_INITIAL_BLOCKLEN) {
if (ctcm_checkalloc_buffer(ch))
@@ -524,9 +536,9 @@ static void chx_rxidle(fsm_instance *fi, int event, void *arg)
} else
fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
} else {
- if (do_debug)
- ctcm_pr_debug("%s: Initial RX count %d not %d\n",
- dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
+ CTCM_PR_DEBUG("%s: %s: Initial RX count %d not %d\n",
+ __func__, dev->name,
+ buflen, CTCM_INITIAL_BLOCKLEN);
chx_firstio(fi, event, arg);
}
}
@@ -548,14 +560,12 @@ static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (IS_MPC(ch)) {
timeout = 1500;
- if (do_debug)
- ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
}
fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
fsm_newstate(fi, CTC_STATE_SETUPWAIT);
- if (do_debug_ccw && IS_MPC(ch))
- ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
+ CTCM_CCW_DUMP((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
if (event == CTC_EVENT_TIMER) /* only for timer not yet locked */
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -583,24 +593,12 @@ static void ctcm_chx_setmode(fsm_instance *fi, int event, void *arg)
*/
static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
{
- struct channel *ch = arg;
- int rc;
- struct net_device *dev;
+ struct channel *ch = arg;
unsigned long saveflags;
+ int rc;
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
- if (ch == NULL) {
- ctcm_pr_warn("chx_start ch=NULL\n");
- return;
- }
- if (ch->netdev == NULL) {
- ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
- return;
- }
- dev = ch->netdev;
-
- if (do_debug)
- ctcm_pr_debug("%s: %s channel start\n", dev->name,
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
if (ch->trans_skb != NULL) {
@@ -618,11 +616,12 @@ static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
ch->ccw[1].count = 0;
}
if (ctcm_checkalloc_buffer(ch)) {
- ctcm_pr_notice("%s: %s trans_skb allocation delayed "
- "until first transfer\n", dev->name,
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): %s trans_skb alloc delayed "
+ "until first transfer",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
}
-
ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[0].count = 0;
@@ -661,7 +660,6 @@ static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
int rc;
int oldstate;
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
fsm_deltimer(&ch->timer);
if (IS_MPC(ch))
fsm_deltimer(&ch->sweep_timer);
@@ -684,7 +682,7 @@ static void ctcm_chx_haltio(fsm_instance *fi, int event, void *arg)
fsm_deltimer(&ch->timer);
if (event != CTC_EVENT_STOP) {
fsm_newstate(fi, oldstate);
- ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
+ ctcm_ccw_check_rc(ch, rc, (char *)__func__);
}
}
}
@@ -703,7 +701,9 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state,
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+ "%s(%s): %s[%d]\n",
+ CTCM_FUNTAIL, dev->name, ch->id, state);
fsm_deltimer(&ch->timer);
if (IS_MPC(ch))
@@ -743,7 +743,6 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state,
*/
static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
{
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
}
@@ -771,7 +770,6 @@ static void ctcm_chx_stop(fsm_instance *fi, int event, void *arg)
*/
static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
{
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
}
@@ -809,8 +807,8 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg)
}
CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
- "%s : %s error during %s channel setup state=%s\n",
- dev->name, ctc_ch_event_names[event],
+ "%s(%s) : %s error during %s channel setup state=%s\n",
+ CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event],
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
fsm_getstate_str(fi));
@@ -838,10 +836,12 @@ static void ctcm_chx_restart(fsm_instance *fi, int event, void *arg)
int oldstate;
int rc;
- CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s: %s[%d] of %s\n",
+ CTCM_FUNTAIL, ch->id, event, dev->name);
+
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s: %s channel restart\n", dev->name,
- (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+
fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
oldstate = fsm_getstate(fi);
fsm_newstate(fi, CTC_STATE_STARTWAIT);
@@ -876,13 +876,10 @@ static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
if (event == CTC_EVENT_TIMER) {
if (!IS_MPCDEV(dev))
/* TODO : check if MPC deletes timer somewhere */
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s: Timeout during RX init handshake\n",
- dev->name);
if (ch->retry++ < 3)
ctcm_chx_restart(fi, event, arg);
else {
@@ -907,9 +904,10 @@ static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): RX %s busy, init. fail",
+ CTCM_FUNTAIL, dev->name, ch->id);
fsm_newstate(fi, CTC_STATE_RXERR);
- ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
}
@@ -927,11 +925,10 @@ static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg)
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
- CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s: %s: remote disconnect - re-init ...",
+ CTCM_FUNTAIL, dev->name);
fsm_deltimer(&ch->timer);
- if (do_debug)
- ctcm_pr_debug("%s: Got remote disconnect, "
- "re-initializing ...\n", dev->name);
/*
* Notify device statemachine
*/
@@ -961,8 +958,6 @@ static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
if (event == CTC_EVENT_TIMER) {
fsm_deltimer(&ch->timer);
- CTCM_DBF_DEV_NAME(ERROR, dev,
- "Timeout during TX init handshake");
if (ch->retry++ < 3)
ctcm_chx_restart(fi, event, arg);
else {
@@ -971,9 +966,8 @@ static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg)
}
} else {
CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
- "%s : %s error during channel setup state=%s",
- dev->name, ctc_ch_event_names[event],
- fsm_getstate_str(fi));
+ "%s(%s): %s in %s", CTCM_FUNTAIL, ch->id,
+ ctc_ch_event_names[event], fsm_getstate_str(fi));
ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
}
@@ -993,15 +987,15 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct sk_buff *skb;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("Enter: %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
fsm_deltimer(&ch->timer);
if (ch->retry++ > 3) {
struct mpc_group *gptr = priv->mpcg;
- ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
- dev->name);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s: %s: retries exceeded",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
/* call restart if not MPC or if MPC and mpcg fsm is ready.
use gptr as mpc indicator */
@@ -1010,7 +1004,9 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
goto done;
}
- ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s : %s: retry %d",
+ CTCM_FUNTAIL, ch->id, ch->retry);
skb = skb_peek(&ch->io_queue);
if (skb) {
int rc = 0;
@@ -1018,8 +1014,9 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg)
clear_normalized_cda(&ch->ccw[4]);
ch->ccw[4].count = skb->len;
if (set_normalized_cda(&ch->ccw[4], skb->data)) {
- ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
- dev->name);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s: %s: IDAL alloc failed",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
ctcm_chx_restart(fi, event, arg);
goto done;
@@ -1061,22 +1058,21 @@ static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg)
struct channel *ch = arg;
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
+ int rd = CHANNEL_DIRECTION(ch->flags);
- CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
fsm_deltimer(&ch->timer);
- ctcm_pr_warn("%s %s : unrecoverable channel error\n",
- CTC_DRIVER_NAME, dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s: %s: %s unrecoverable channel error",
+ CTCM_FUNTAIL, ch->id, rd == READ ? "RX" : "TX");
+
if (IS_MPC(ch)) {
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
}
-
- if (CHANNEL_DIRECTION(ch->flags) == READ) {
- ctcm_pr_debug("%s: RX I/O error\n", dev->name);
+ if (rd == READ) {
fsm_newstate(fi, CTC_STATE_RXERR);
fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
} else {
- ctcm_pr_debug("%s: TX I/O error\n", dev->name);
fsm_newstate(fi, CTC_STATE_TXERR);
fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
}
@@ -1216,27 +1212,27 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
struct sk_buff *skb;
int first = 1;
int i;
- struct timespec done_stamp;
__u32 data_space;
unsigned long duration;
struct sk_buff *peekskb;
int rc;
struct th_header *header;
struct pdu *p_header;
+ struct timespec done_stamp = current_kernel_time(); /* xtime */
- if (do_debug)
- ctcm_pr_debug("%s cp:%i enter: %s()\n",
- dev->name, smp_processor_id(), __FUNCTION__);
+ CTCM_PR_DEBUG("Enter %s: %s cp:%i\n",
+ __func__, dev->name, smp_processor_id());
- done_stamp = current_kernel_time(); /* xtime */
- duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
- + (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+ duration =
+ (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
if (duration > ch->prof.tx_time)
ch->prof.tx_time = duration;
if (ch->irb->scsw.cmd.count != 0)
- ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
- dev->name, ch->irb->scsw.cmd.count);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s(%s): TX not complete, remaining %d bytes",
+ CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
fsm_deltimer(&ch->timer);
while ((skb = skb_dequeue(&ch->io_queue))) {
priv->stats.tx_packets++;
@@ -1250,7 +1246,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
}
spin_lock(&ch->collect_lock);
clear_normalized_cda(&ch->ccw[4]);
-
if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
spin_unlock(&ch->collect_lock);
fsm_newstate(fi, CTC_STATE_TXIDLE);
@@ -1269,17 +1264,13 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
i = 0;
-
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() building "
- "trans_skb from collect_q \n", __FUNCTION__);
-
+ p_header = NULL;
data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
- " data_space:%04x\n", __FUNCTION__, data_space);
- p_header = NULL;
+ CTCM_PR_DBGDATA("%s: building trans_skb from collect_q"
+ " data_space:%04x\n",
+ __func__, data_space);
+
while ((skb = skb_dequeue(&ch->collect_queue))) {
memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
p_header = (struct pdu *)
@@ -1290,15 +1281,12 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
else
p_header->pdu_flag |= 0x20;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
- __FUNCTION__, ch->trans_skb->len);
- ctcm_pr_debug("ctcmpc: %s() pdu header and data"
- " for up to 32 bytes sent to vtam\n",
- __FUNCTION__);
- ctcmpc_dumpit((char *)p_header,
- min_t(int, skb->len, 32));
- }
+ CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+ __func__, ch->trans_skb->len);
+ CTCM_PR_DBGDATA("%s: pdu header and data for up"
+ " to 32 bytes sent to vtam\n", __func__);
+ CTCM_D3_DUMP((char *)p_header, min_t(int, skb->len, 32));
+
ch->collect_len -= skb->len;
data_space -= skb->len;
priv->stats.tx_packets++;
@@ -1314,46 +1302,38 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
if (p_header)
p_header->pdu_flag |= PDU_LAST; /*Say it's the last one*/
header = kzalloc(TH_HEADER_LENGTH, gfp_type());
-
if (!header) {
- printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
- ": Data Lost \n", __FUNCTION__);
spin_unlock(&ch->collect_lock);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto done;
}
-
header->th_ch_flag = TH_HAS_PDU; /* Normal data */
ch->th_seq_num++;
header->th_seq_num = ch->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("%s: ToVTAM_th_seq= %08x\n" ,
+ __func__, ch->th_seq_num);
memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
TH_HEADER_LENGTH); /* put the TH on the packet */
kfree(header);
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
- __FUNCTION__, ch->trans_skb->len);
-
- ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
- "data to vtam from collect_q\n", __FUNCTION__);
- ctcmpc_dumpit((char *)ch->trans_skb->data,
+ CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+ __func__, ch->trans_skb->len);
+ CTCM_PR_DBGDATA("%s: up-to-50 bytes of trans_skb "
+ "data to vtam from collect_q\n", __func__);
+ CTCM_D3_DUMP((char *)ch->trans_skb->data,
min_t(int, ch->trans_skb->len, 50));
- }
spin_unlock(&ch->collect_lock);
clear_normalized_cda(&ch->ccw[1]);
if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
dev_kfree_skb_any(ch->trans_skb);
ch->trans_skb = NULL;
- printk(KERN_WARNING
- "ctcmpc: %s()CCW failure - data lost\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s: %s: IDAL alloc failed",
+ CTCM_FUNTAIL, ch->id);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
return;
}
@@ -1373,7 +1353,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
}
done:
ctcm_clear_busy(dev);
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1393,26 +1372,25 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
struct mpc_group *grp = priv->mpcg;
struct sk_buff *skb = ch->trans_skb;
struct sk_buff *new_skb;
- unsigned long saveflags = 0; /* avoids compiler warning */
+ unsigned long saveflags = 0; /* avoids compiler warning */
int len = ch->max_bufsize - ch->irb->scsw.cmd.count;
- if (do_debug_data) {
- CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
- dev->name, smp_processor_id(), ch->id);
- CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
- "len: %04x\n", ch->max_bufsize, len);
- }
+ CTCM_PR_DEBUG("%s: %s: cp:%i %s maxbuf : %04x, len: %04x\n",
+ CTCM_FUNTAIL, dev->name, smp_processor_id(),
+ ch->id, ch->max_bufsize, len);
fsm_deltimer(&ch->timer);
if (skb == NULL) {
- ctcm_pr_debug("ctcmpc exit: %s() TRANS_SKB = NULL \n",
- __FUNCTION__);
- goto again;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): TRANS_SKB = NULL",
+ CTCM_FUNTAIL, dev->name);
+ goto again;
}
if (len < TH_HEADER_LENGTH) {
- ctcm_pr_info("%s: got packet with invalid length %d\n",
- dev->name, len);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): packet length %d to short",
+ CTCM_FUNTAIL, dev->name, len);
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
} else {
@@ -1422,11 +1400,9 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
if (new_skb == NULL) {
- printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
- __FUNCTION__);
- printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
- " - DATA LOST - MPC FAILED\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%d): skb allocation failed",
+ CTCM_FUNTAIL, dev->name);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
goto again;
}
@@ -1479,9 +1455,8 @@ again:
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: %s, ch=0x%p, id=%s\n",
+ __func__, dev->name, ch, ch->id);
}
@@ -1497,15 +1472,16 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
struct channel *ch = arg;
struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *gptr = priv->mpcg;
+
+ CTCM_PR_DEBUG("Enter %s: id=%s, ch=0x%p\n",
+ __func__, ch->id, ch);
+
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+ "%s: %s: chstate:%i, grpstate:%i, prot:%i\n",
+ CTCM_FUNTAIL, ch->id, fsm_getstate(fi),
+ fsm_getstate(gptr->fsm), ch->protocol);
- if (do_debug) {
- struct mpc_group *gptr = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
- ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
- __FUNCTION__, ch->id, fsm_getstate(fi),
- fsm_getstate(gptr->fsm), ch->protocol);
- }
if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
@@ -1531,9 +1507,8 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg)
? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: id=%s, ch=0x%p\n",
+ __func__, ch->id, ch);
return;
}
@@ -1556,12 +1531,9 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
unsigned long saveflags = 0; /* avoids compiler warning */
fsm_deltimer(&ch->timer);
- ctcm_pr_debug("%s cp:%i enter: %s()\n",
- dev->name, smp_processor_id(), __FUNCTION__);
- if (do_debug)
- ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
- __FUNCTION__, ch->id,
- fsm_getstate(fi), fsm_getstate(grp->fsm));
+ CTCM_PR_DEBUG("%s: %s: %s: cp:%i, chstate:%i grpstate:%i\n",
+ __func__, ch->id, dev->name, smp_processor_id(),
+ fsm_getstate(fi), fsm_getstate(grp->fsm));
fsm_newstate(fi, CTC_STATE_RXIDLE);
/* XID processing complete */
@@ -1575,9 +1547,7 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
skb_reset_tail_pointer(ch->trans_skb);
ch->trans_skb->len = 0;
ch->ccw[1].count = ch->max_bufsize;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&ch->ccw[0],
- sizeof(struct ccw1) * 3);
+ CTCM_CCW_DUMP((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
if (event == CTC_EVENT_START)
/* see remark about conditional locking */
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -1598,9 +1568,6 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg)
fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s %s()\n",
- dev->name, __FUNCTION__);
return;
}
@@ -1616,13 +1583,9 @@ static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- if (do_debug) {
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
- "GrpState:%s ChState:%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- }
+ CTCM_PR_DEBUG("%s(%s): %s(ch=0x%p), cp=%i, ChStat:%s, GrpStat:%s\n",
+ __func__, dev->name, ch->id, ch, smp_processor_id(),
+ fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
switch (fsm_getstate(grp->fsm)) {
case MPCG_STATE_XID2INITW:
@@ -1664,11 +1627,7 @@ static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg)
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
return;
-
}
/*
@@ -1683,11 +1642,9 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
- dev->name,
- __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
+ CTCM_PR_DEBUG("%s(%s): %s\n ChState:%s GrpState:%s\n",
+ __func__, dev->name, ch->id,
+ fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
fsm_deltimer(&ch->timer);
@@ -1750,16 +1707,12 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg)
if (ch->in_mpcgroup)
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
else
- printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
- " been added to group\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): channel %s not added to group",
+ CTCM_FUNTAIL, dev->name, ch->id);
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
- __FUNCTION__, dev->name, ch, ch->id);
-
return;
-
}
/*
@@ -1774,13 +1727,7 @@ static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc enter: %s %s() %s \nGrpState:%s ChState:%s\n",
- dev->name, __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
-
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
-
return;
}
@@ -1802,19 +1749,16 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
int rc = 0;
unsigned long saveflags = 0;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ach, ach->id);
+ CTCM_PR_DEBUG("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ach, ach->id);
if (grp->in_sweep == 0)
goto done;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, wch->th_seq_num);
- ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
- __FUNCTION__, rch->th_seq_num);
- }
+ CTCM_PR_DBGDATA("%s: 1: ToVTAM_th_seq= %08x\n" ,
+ __func__, wch->th_seq_num);
+ CTCM_PR_DBGDATA("%s: 1: FromVTAM_th_seq= %08x\n" ,
+ __func__, rch->th_seq_num);
if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
/* give the previous IO time to complete */
@@ -1853,11 +1797,9 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
header->sw.th_last_seq = wch->th_seq_num;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
-
- ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
- ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
+ CTCM_CCW_DUMP((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
+ CTCM_PR_DBGDATA("%s: sweep packet\n", __func__);
+ CTCM_D3_DUMP((char *)header, TH_SWEEP_LENGTH);
fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
fsm_newstate(wch->fsm, CTC_STATE_TX);
@@ -1876,19 +1818,13 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
ctcm_clear_busy_do(dev);
}
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, wch->th_seq_num);
- ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
- __FUNCTION__, rch->th_seq_num);
- }
+ CTCM_PR_DBGDATA("%s: To-/From-VTAM_th_seq = %08x/%08x\n" ,
+ __func__, wch->th_seq_num, rch->th_seq_num);
if (rc != 0)
ctcm_ccw_check_rc(wch, rc, "send sweep");
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s() %s\n", __FUNCTION__, ach->id);
return;
}
@@ -2149,9 +2085,8 @@ static void dev_action_stop(fsm_instance *fi, int event, void *arg)
struct channel *ch = priv->channel[direction];
fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
ch->th_seq_num = 0x00;
- if (do_debug)
- ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DEBUG("%s: CH_th_seq= %08x\n",
+ __func__, ch->th_seq_num);
}
if (IS_MPC(priv))
fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
@@ -2199,8 +2134,11 @@ static void dev_action_chup(fsm_instance *fi, int event, void *arg)
{
struct net_device *dev = arg;
struct ctcm_priv *priv = dev->priv;
+ int dev_stat = fsm_getstate(fi);
- CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+ "%s(%s): priv = %p [%d,%d]\n ", CTCM_FUNTAIL,
+ dev->name, dev->priv, dev_stat, event);
switch (fsm_getstate(fi)) {
case DEV_STATE_STARTWAIT_RXTX:
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 6b13c1c1beb..126a3ebb8ab 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -84,20 +84,19 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
skb_pull(pskb, LL_HEADER_LENGTH);
if ((ch->protocol == CTCM_PROTO_S390) &&
(header->type != ETH_P_IP)) {
-
if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+ ch->logflags |= LOG_FLAG_ILLEGALPKT;
/*
* Check packet type only if we stick strictly
* to S/390's protocol of OS390. This only
* supports IP. Otherwise allow any packet
* type.
*/
- ctcm_pr_warn("%s Illegal packet type 0x%04x "
- "received, dropping\n",
- dev->name, header->type);
- ch->logflags |= LOG_FLAG_ILLEGALPKT;
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Illegal packet type 0x%04x"
+ " - dropping",
+ CTCM_FUNTAIL, dev->name, header->type);
}
-
priv->stats.rx_dropped++;
priv->stats.rx_frame_errors++;
return;
@@ -105,11 +104,11 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
pskb->protocol = ntohs(header->type);
if (header->length <= LL_HEADER_LENGTH) {
if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
- ctcm_pr_warn(
- "%s Illegal packet size %d "
- "received (MTU=%d blocklen=%d), "
- "dropping\n", dev->name, header->length,
- dev->mtu, len);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Illegal packet size %d(%d,%d)"
+ "- dropping",
+ CTCM_FUNTAIL, dev->name,
+ header->length, dev->mtu, len);
ch->logflags |= LOG_FLAG_ILLEGALSIZE;
}
@@ -122,10 +121,10 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
if ((header->length > skb_tailroom(pskb)) ||
(header->length > len)) {
if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
- ctcm_pr_warn(
- "%s Illegal packet size %d (beyond the"
- " end of received data), dropping\n",
- dev->name, header->length);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Packet size %d (overrun)"
+ " - dropping", CTCM_FUNTAIL,
+ dev->name, header->length);
ch->logflags |= LOG_FLAG_OVERRUN;
}
@@ -139,9 +138,9 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
skb = dev_alloc_skb(pskb->len);
if (!skb) {
if (!(ch->logflags & LOG_FLAG_NOMEM)) {
- ctcm_pr_warn(
- "%s Out of memory in ctcm_unpack_skb\n",
- dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): MEMORY allocation error",
+ CTCM_FUNTAIL, dev->name);
ch->logflags |= LOG_FLAG_NOMEM;
}
priv->stats.rx_dropped++;
@@ -184,7 +183,7 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb)
*/
static void channel_free(struct channel *ch)
{
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, ch->id);
ch->flags &= ~CHANNEL_FLAGS_INUSE;
fsm_newstate(ch->fsm, CTC_STATE_IDLE);
}
@@ -251,19 +250,12 @@ static struct channel *channel_get(enum channel_types type,
{
struct channel *ch = channels;
- if (do_debug) {
- char buf[64];
- sprintf(buf, "%s(%d, %s, %d)\n",
- CTCM_FUNTAIL, type, id, direction);
- CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
- }
while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
ch = ch->next;
if (!ch) {
- char buf[64];
- sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%d, %s, %d) not found in channel list\n",
CTCM_FUNTAIL, type, id, direction);
- CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
} else {
if (ch->flags & CHANNEL_FLAGS_INUSE)
ch = NULL;
@@ -283,8 +275,9 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
if (!IS_ERR(irb))
return 0;
- CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
- PTR_ERR(irb), cdev->dev.bus_id);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
+ "irb error %ld on device %s\n",
+ PTR_ERR(irb), cdev->dev.bus_id);
switch (PTR_ERR(irb)) {
case -EIO:
@@ -307,58 +300,85 @@ static long ctcm_check_irb_error(struct ccw_device *cdev, struct irb *irb)
* ch The channel, the sense code belongs to.
* sense The sense code to inspect.
*/
-static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
+static inline void ccw_unit_check(struct channel *ch, __u8 sense)
{
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+
if (sense & SNS0_INTERVENTION_REQ) {
if (sense & 0x01) {
- ctcm_pr_debug("%s: Interface disc. or Sel. reset "
- "(remote)\n", ch->id);
+ if (ch->sense_rc != 0x01) {
+ ctcm_pr_debug("%s: Interface disc. or Sel. "
+ "reset (remote)\n", ch->id);
+ ch->sense_rc = 0x01;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
} else {
- ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
+ if (ch->sense_rc != SNS0_INTERVENTION_REQ) {
+ ctcm_pr_debug("%s: System reset (remote)\n",
+ ch->id);
+ ch->sense_rc = SNS0_INTERVENTION_REQ;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
}
} else if (sense & SNS0_EQUIPMENT_CHECK) {
if (sense & SNS0_BUS_OUT_CHECK) {
- ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
- ch->id);
+ if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): remote HW error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_BUS_OUT_CHECK;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
} else {
- ctcm_pr_warn("%s: Read-data parity error (remote)\n",
- ch->id);
+ if (ch->sense_rc != SNS0_EQUIPMENT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): remote read parity error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_EQUIPMENT_CHECK;
+ }
fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
}
} else if (sense & SNS0_BUS_OUT_CHECK) {
- if (sense & 0x04) {
- ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
+ if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): BUS OUT error %02x",
+ CTCM_FUNTAIL, ch->id, sense);
+ ch->sense_rc = SNS0_BUS_OUT_CHECK;
+ }
+ if (sense & 0x04) /* data-streaming timeout */
fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
- } else {
- ctcm_pr_warn("%s: Data-transfer parity error\n",
- ch->id);
+ else /* Data-transfer parity error */
fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
- }
} else if (sense & SNS0_CMD_REJECT) {
- ctcm_pr_warn("%s: Command reject\n", ch->id);
+ if (ch->sense_rc != SNS0_CMD_REJECT) {
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Command rejected",
+ CTCM_FUNTAIL, ch->id);
+ ch->sense_rc = SNS0_CMD_REJECT;
+ }
} else if (sense == 0) {
- ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Unit check ZERO",
+ CTCM_FUNTAIL, ch->id);
fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
} else {
- ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
- ch->id, sense);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+ "%s(%s): Unit check code %02x unknown",
+ CTCM_FUNTAIL, ch->id, sense);
fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
}
}
int ctcm_ch_alloc_buffer(struct channel *ch)
{
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
-
clear_normalized_cda(&ch->ccw[1]);
ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
if (ch->trans_skb == NULL) {
- ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
- ch->id,
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): %s trans_skb allocation error",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
return -ENOMEM;
}
@@ -367,9 +387,9 @@ int ctcm_ch_alloc_buffer(struct channel *ch)
if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
dev_kfree_skb(ch->trans_skb);
ch->trans_skb = NULL;
- ctcm_pr_warn("%s: set_normalized_cda for %s "
- "trans_skb failed, dropping packets\n",
- ch->id,
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): %s set norm_cda failed",
+ CTCM_FUNTAIL, ch->id,
(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
return -ENOMEM;
}
@@ -516,7 +536,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
- return -EBUSY;
+ return -ENOMEM;
}
skb_reset_tail_pointer(ch->trans_skb);
@@ -570,15 +590,12 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
struct th_sweep *header;
struct sk_buff *sweep_skb;
struct channel *ch;
- int rc = 0;
+ /* int rc = 0; */
priv = dev->priv;
grp = priv->mpcg;
ch = priv->channel[WRITE];
- if (do_debug)
- MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
-
/* sweep processing is not complete until response and request */
/* has completed for all read channels in group */
if (grp->in_sweep == 0) {
@@ -590,17 +607,16 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
if (sweep_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc sweep_skb\n");
- rc = -ENOMEM;
- goto done;
+ /* rc = -ENOMEM; */
+ goto nomem;
}
header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
if (!header) {
dev_kfree_skb_any(sweep_skb);
- rc = -ENOMEM;
- goto done;
+ /* rc = -ENOMEM; */
+ goto nomem;
}
header->th.th_seg = 0x00 ;
@@ -621,12 +637,10 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
return;
-done:
- if (rc != 0) {
- grp->in_sweep = 0;
- ctcm_clear_busy(dev);
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
- }
+nomem:
+ grp->in_sweep = 0;
+ ctcm_clear_busy(dev);
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
return;
}
@@ -648,11 +662,9 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
unsigned long saveflags = 0; /* avoids compiler warning */
__u16 block_len;
- if (do_debug)
- ctcm_pr_debug(
- "ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
- __FUNCTION__, dev->name, smp_processor_id(), ch,
- ch->id, fsm_getstate_str(ch->fsm));
+ CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n",
+ __func__, dev->name, smp_processor_id(), ch,
+ ch->id, fsm_getstate_str(ch->fsm));
if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -660,14 +672,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
if (!p_header) {
- printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
- " Data Lost \n", __FUNCTION__);
-
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
}
p_header->pdu_offset = skb->len;
@@ -682,13 +688,10 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
PDU_HEADER_LENGTH);
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() Putting on collect_q"
- " - skb len: %04x \n", __FUNCTION__, skb->len);
- ctcm_pr_debug("ctcm: %s() pdu header and data"
- " for up to 32 bytes\n", __FUNCTION__);
- ctcmpc_dump32((char *)skb->data, skb->len);
- }
+ CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n"
+ "pdu header and data for up to 32 bytes:\n",
+ __func__, dev->name, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
skb_queue_tail(&ch->collect_queue, skb);
ch->collect_len += skb->len;
@@ -713,12 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
if (hi) {
nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
if (!nskb) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
- "- Data Lost \n", __FUNCTION__);
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
} else {
memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
atomic_inc(&nskb->users);
@@ -730,15 +728,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
- if (!p_header) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
- ": Data Lost \n", __FUNCTION__);
-
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
- }
+ if (!p_header)
+ goto nomem_exit;
p_header->pdu_offset = skb->len;
p_header->pdu_proto = 0x01;
@@ -768,15 +759,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
header = kmalloc(TH_HEADER_LENGTH, gfp_type());
-
- if (!header) {
- printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
- __FUNCTION__);
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
- }
+ if (!header)
+ goto nomem_exit;
header->th_seg = 0x00;
header->th_ch_flag = TH_HAS_PDU; /* Normal data */
@@ -785,41 +769,31 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->th_seq_num++;
header->th_seq_num = ch->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" ,
+ __func__, dev->name, ch->th_seq_num);
/* put the TH on the packet */
memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
kfree(header);
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
- __FUNCTION__, skb->len);
- ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
- "bytes sent to vtam\n", __FUNCTION__);
- ctcmpc_dump32((char *)skb->data, skb->len);
- }
+ CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for "
+ "up to 32 bytes sent to vtam:\n",
+ __func__, dev->name, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
ch->ccw[4].count = skb->len;
if (set_normalized_cda(&ch->ccw[4], skb->data)) {
/*
- * idal allocation failed, try via copying to
- * trans_skb. trans_skb usually has a pre-allocated
- * idal.
+ * idal allocation failed, try via copying to trans_skb.
+ * trans_skb usually has a pre-allocated idal.
*/
if (ctcm_checkalloc_buffer(ch)) {
/*
- * Remove our header. It gets added
- * again on retransmit.
+ * Remove our header.
+ * It gets added again on retransmit.
*/
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
- " Data Lost \n", __FUNCTION__);
- fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
- goto done;
+ goto nomem_exit;
}
skb_reset_tail_pointer(ch->trans_skb);
@@ -829,14 +803,11 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
atomic_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
- __FUNCTION__, ch->trans_skb->len);
- ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
- " sent to vtam\n", __FUNCTION__);
- ctcmpc_dump32((char *)ch->trans_skb->data,
- ch->trans_skb->len);
- }
+ CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
+ "up to 32 bytes sent to vtam:\n",
+ __func__, dev->name, ch->trans_skb->len);
+ CTCM_D3_DUMP((char *)ch->trans_skb->data,
+ min_t(int, 32, ch->trans_skb->len));
} else {
skb_queue_tail(&ch->io_queue, skb);
ccw_idx = 3;
@@ -865,13 +836,21 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
}
- if (ch->th_seq_num > 0xf0000000) /* Chose 4Billion at random. */
+ if (ch->th_seq_num > 0xf0000000) /* Chose at random. */
ctcmpc_send_sweep_req(ch);
+ goto done;
+nomem_exit:
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_CRIT,
+ "%s(%s): MEMORY allocation ERROR\n",
+ CTCM_FUNTAIL, ch->id);
+ rc = -ENOMEM;
+ atomic_dec(&skb->users);
+ dev_kfree_skb_any(skb);
+ fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
done:
- if (do_debug)
- ctcm_pr_debug("ctcm exit: %s %s()\n", dev->name, __FUNCTION__);
- return 0;
+ CTCM_PR_DEBUG("Exit %s(%s)\n", __func__, dev->name);
+ return rc;
}
/**
@@ -888,20 +867,19 @@ done:
/* first merge version - leaving both functions separated */
static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
{
- int rc = 0;
- struct ctcm_priv *priv;
-
- CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
- priv = dev->priv;
+ struct ctcm_priv *priv = dev->priv;
if (skb == NULL) {
- ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): NULL sk_buff passed",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
return 0;
}
if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
- ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
- dev->name, LL_HEADER_LENGTH + 2);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s(%s): Got sk_buff with head room < %ld bytes",
+ CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
dev_kfree_skb(skb);
priv->stats.tx_dropped++;
return 0;
@@ -925,51 +903,43 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
- rc = 1;
- return rc;
+ return 1;
+ return 0;
}
/* unmerged MPC variant of ctcm_tx */
static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
{
int len = 0;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
struct sk_buff *newskb = NULL;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
- __FUNCTION__, (unsigned long)skb);
-
- CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
- "ctcmpc enter: %s(): skb:%0lx\n",
- __FUNCTION__, (unsigned long)skb);
-
- priv = dev->priv;
- grp = priv->mpcg;
/*
* Some sanity checks ...
*/
if (skb == NULL) {
- ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): NULL sk_buff passed",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
goto done;
}
if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
- CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
- "%s: Got sk_buff with head room < %ld bytes\n",
- dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s(%s): Got sk_buff with head room < %ld bytes",
+ CTCM_FUNTAIL, dev->name,
+ TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
- if (do_debug_data)
- ctcmpc_dump32((char *)skb->data, skb->len);
+ CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
if (!newskb) {
- printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
- "Data Lost\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+ "%s: %s: __dev_alloc_skb failed",
+ __func__, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
@@ -993,9 +963,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
dev_kfree_skb_any(skb);
- printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
- "NOT ACTIVE - DROPPED\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): inactive MPCGROUP - dropped",
+ CTCM_FUNTAIL, dev->name);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
priv->stats.tx_carrier_errors++;
@@ -1003,8 +973,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
}
if (ctcm_test_and_set_busy(dev)) {
- printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): device busy - dropped",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
@@ -1015,12 +986,9 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
- printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
- ": Data Lost \n",
- __FUNCTION__);
- printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
- " - UNRECOVERABLE DATA LOSS\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): device error - dropped",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
priv->stats.tx_dropped++;
priv->stats.tx_errors++;
@@ -1054,8 +1022,6 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu)
struct ctcm_priv *priv;
int max_bufsize;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
if (new_mtu < 576 || new_mtu > 65527)
return -EINVAL;
@@ -1087,30 +1053,13 @@ static struct net_device_stats *ctcm_stats(struct net_device *dev)
return &((struct ctcm_priv *)dev->priv)->stats;
}
-
-static void ctcm_netdev_unregister(struct net_device *dev)
-{
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
- if (!dev)
- return;
- unregister_netdev(dev);
-}
-
-static int ctcm_netdev_register(struct net_device *dev)
-{
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
- return register_netdev(dev);
-}
-
static void ctcm_free_netdevice(struct net_device *dev)
{
struct ctcm_priv *priv;
struct mpc_group *grp;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
- if (!dev)
- return;
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s(%s)", CTCM_FUNTAIL, dev->name);
priv = dev->priv;
if (priv) {
grp = priv->mpcg;
@@ -1171,7 +1120,9 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
if (!dev) {
- ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
+ "%s: MEMORY allocation ERROR",
+ CTCM_FUNTAIL);
return NULL;
}
dev->priv = priv;
@@ -1209,6 +1160,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
}
CTCMY_DBF_DEV(SETUP, dev, "finished");
+
return dev;
}
@@ -1226,18 +1178,24 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
struct net_device *dev;
struct ctcm_priv *priv;
struct ccwgroup_device *cgdev;
+ int cstat;
+ int dstat;
+
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id);
- CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
if (ctcm_check_irb_error(cdev, irb))
return;
cgdev = dev_get_drvdata(&cdev->dev);
+ cstat = irb->scsw.cmd.cstat;
+ dstat = irb->scsw.cmd.dstat;
+
/* Check for unsolicited interrupts. */
if (cgdev == NULL) {
- ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
- cdev->dev.bus_id, irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
+ ctcm_pr_warn("ctcm: Got unsolicited irq: c-%02x d-%02x\n",
+ cstat, dstat);
return;
}
@@ -1254,26 +1212,22 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
return;
}
- dev = (struct net_device *)(ch->netdev);
+ dev = ch->netdev;
if (dev == NULL) {
ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
- __FUNCTION__, cdev->dev.bus_id, ch);
+ __func__, cdev->dev.bus_id, ch);
return;
}
- if (do_debug)
- ctcm_pr_debug("%s: interrupt for device: %s "
- "received c-%02x d-%02x\n",
- dev->name,
- ch->id,
- irb->scsw.cmd.cstat,
- irb->scsw.cmd.dstat);
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+ "%s(%s): int. for %s: cstat=%02x dstat=%02x",
+ CTCM_FUNTAIL, dev->name, ch->id, cstat, dstat);
/* Copy interruption response block. */
memcpy(ch->irb, irb, sizeof(struct irb));
- /* Check for good subchannel return code, otherwise error message */
if (irb->scsw.cmd.cstat) {
+ /* Check for good subchannel return code, otherwise error message */
fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
dev->name, ch->id, irb->scsw.cmd.cstat,
@@ -1283,6 +1237,11 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
/* Check the reason-code of a unit check */
if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+ if ((irb->ecw[0] & ch->sense_rc) == 0)
+ /* print it only once */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+ "%s(%s): sense=%02x, ds=%02x",
+ CTCM_FUNTAIL, ch->id, irb->ecw[0], dstat);
ccw_unit_check(ch, irb->ecw[0]);
return;
}
@@ -1320,14 +1279,18 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
struct ctcm_priv *priv;
int rc;
- CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s %p",
+ __func__, cgdev);
if (!get_device(&cgdev->dev))
return -ENODEV;
priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
if (!priv) {
- ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+ "%s: memory allocation failure",
+ CTCM_FUNTAIL);
put_device(&cgdev->dev);
return -ENOMEM;
}
@@ -1364,10 +1327,13 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
int ccw_num;
int rc = 0;
- CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "%s(%s), type %d, proto %d",
+ __func__, cdev->dev.bus_id, type, priv->protocol);
+
ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
if (ch == NULL)
- goto nomem_return;
+ return -ENOMEM;
ch->protocol = priv->protocol;
if (IS_MPC(priv)) {
@@ -1478,7 +1444,7 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
"%s (%s) already in list, using old entry",
- __FUNCTION__, (*c)->id);
+ __func__, (*c)->id);
goto free_return;
}
@@ -1498,11 +1464,10 @@ static int add_channel(struct ccw_device *cdev, enum channel_types type,
return 0;
nomem_return:
- ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
rc = -ENOMEM;
free_return: /* note that all channel pointers are 0 or valid */
- kfree(ch->ccw); /* TODO: check that again */
+ kfree(ch->ccw);
kfree(ch->discontact_th);
kfree_fsm(ch->fsm);
kfree(ch->irb);
@@ -1540,48 +1505,48 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
enum channel_types type;
struct ctcm_priv *priv;
struct net_device *dev;
+ struct ccw_device *cdev0;
+ struct ccw_device *cdev1;
int ret;
- CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
priv = dev_get_drvdata(&cgdev->dev);
if (!priv)
return -ENODEV;
- type = get_channel_type(&cgdev->cdev[0]->id);
+ cdev0 = cgdev->cdev[0];
+ cdev1 = cgdev->cdev[1];
+
+ type = get_channel_type(&cdev0->id);
- snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
- snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+ snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id);
+ snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id);
- ret = add_channel(cgdev->cdev[0], type, priv);
+ ret = add_channel(cdev0, type, priv);
if (ret)
return ret;
- ret = add_channel(cgdev->cdev[1], type, priv);
+ ret = add_channel(cdev1, type, priv);
if (ret)
return ret;
- ret = ccw_device_set_online(cgdev->cdev[0]);
+ ret = ccw_device_set_online(cdev0);
if (ret != 0) {
- CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
- "ccw_device_set_online (cdev[0]) failed ");
- ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
- "with ret = %d\n", ret);
+ /* may be ok to fail now - can be done later */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) set_online rc=%d",
+ CTCM_FUNTAIL, read_id, ret);
}
- ret = ccw_device_set_online(cgdev->cdev[1]);
+ ret = ccw_device_set_online(cdev1);
if (ret != 0) {
- CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
- "ccw_device_set_online (cdev[1]) failed ");
- ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
- "with ret = %d\n", ret);
+ /* may be ok to fail now - can be done later */
+ CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+ "%s(%s) set_online rc=%d",
+ CTCM_FUNTAIL, write_id, ret);
}
dev = ctcm_init_netdevice(priv);
-
- if (dev == NULL) {
- ctcm_pr_warn("ctcm_init_netdevice failed\n");
- goto out;
- }
+ if (dev == NULL)
+ goto out;
for (direction = READ; direction <= WRITE; direction++) {
priv->channel[direction] =
@@ -1590,8 +1555,7 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
if (priv->channel[direction] == NULL) {
if (direction == WRITE)
channel_free(priv->channel[READ]);
- ctcm_free_netdevice(dev);
- goto out;
+ goto out_dev;
}
priv->channel[direction]->netdev = dev;
priv->channel[direction]->protocol = priv->protocol;
@@ -1600,26 +1564,24 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
/* sysfs magic */
SET_NETDEV_DEV(dev, &cgdev->dev);
- if (ctcm_netdev_register(dev) != 0) {
- ctcm_free_netdevice(dev);
- goto out;
- }
+ if (register_netdev(dev))
+ goto out_dev;
if (ctcm_add_attributes(&cgdev->dev)) {
- ctcm_netdev_unregister(dev);
-/* dev->priv = NULL; why that ???? */
- ctcm_free_netdevice(dev);
- goto out;
+ unregister_netdev(dev);
+ goto out_dev;
}
strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
- "setup(%s) ok : r/w = %s / %s, proto : %d",
- dev->name, priv->channel[READ]->id,
+ "setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
+ priv->channel[READ]->id,
priv->channel[WRITE]->id, priv->protocol);
return 0;
+out_dev:
+ ctcm_free_netdevice(dev);
out:
ccw_device_set_offline(cgdev->cdev[1]);
ccw_device_set_offline(cgdev->cdev[0]);
@@ -1658,8 +1620,7 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
channel_free(priv->channel[WRITE]);
if (dev) {
- ctcm_netdev_unregister(dev);
-/* dev->priv = NULL; why that ??? */
+ unregister_netdev(dev);
ctcm_free_netdevice(dev);
}
@@ -1682,13 +1643,16 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev)
static void ctcm_remove_device(struct ccwgroup_device *cgdev)
{
- struct ctcm_priv *priv;
+ struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
- CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
+ BUG_ON(priv == NULL);
+
+ CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+ "removing device %s, r/w = %s/%s, proto : %d",
+ priv->channel[READ]->netdev->name,
+ priv->channel[READ]->id, priv->channel[WRITE]->id,
+ priv->protocol);
- priv = dev_get_drvdata(&cgdev->dev);
- if (!priv)
- return;
if (cgdev->state == CCWGROUP_ONLINE)
ctcm_shutdown_device(cgdev);
ctcm_remove_files(&cgdev->dev);
@@ -1748,8 +1712,6 @@ static int __init ctcm_init(void)
ret = ctcm_register_dbf_views();
if (ret) {
- ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
- "rc = %d\n", ret);
return ret;
}
ret = register_cu3088_discipline(&ctcm_group_driver);
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 95b0c0b6ebc..a72e0feeb27 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -22,9 +22,9 @@
#define CTC_DRIVER_NAME "ctcm"
#define CTC_DEVICE_NAME "ctc"
-#define CTC_DEVICE_GENE "ctc%d"
#define MPC_DEVICE_NAME "mpc"
-#define MPC_DEVICE_GENE "mpc%d"
+#define CTC_DEVICE_GENE CTC_DEVICE_NAME "%d"
+#define MPC_DEVICE_GENE MPC_DEVICE_NAME "%d"
#define CHANNEL_FLAGS_READ 0
#define CHANNEL_FLAGS_WRITE 1
@@ -48,6 +48,30 @@
#define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
#define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
+#define CTCM_PR_DEBUG(fmt, arg...) \
+ do { \
+ if (do_debug) \
+ printk(KERN_DEBUG fmt, ##arg); \
+ } while (0)
+
+#define CTCM_PR_DBGDATA(fmt, arg...) \
+ do { \
+ if (do_debug_data) \
+ printk(KERN_DEBUG fmt, ##arg); \
+ } while (0)
+
+#define CTCM_D3_DUMP(buf, len) \
+ do { \
+ if (do_debug_data) \
+ ctcmpc_dumpit(buf, len); \
+ } while (0)
+
+#define CTCM_CCW_DUMP(buf, len) \
+ do { \
+ if (do_debug_ccw) \
+ ctcmpc_dumpit(buf, len); \
+ } while (0)
+
/*
* CCW commands, used in this driver.
*/
@@ -161,8 +185,9 @@ struct channel {
fsm_instance *fsm; /* finite state machine of this channel */
struct net_device *netdev; /* corresponding net_device */
struct ctcm_profile prof;
- unsigned char *trans_skb_data;
+ __u8 *trans_skb_data;
__u16 logflags;
+ __u8 sense_rc; /* last unit check sense code report control */
};
struct ctcm_priv {
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 044addee64a..49ae1cd25ca 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -149,7 +149,7 @@ void ctcmpc_dumpit(char *buf, int len)
for (ct = 0; ct < len; ct++, ptr++, rptr++) {
if (sw == 0) {
#if (UTS_MACHINE == s390x)
- sprintf(addr, "%16.16lx", (unsigned long)rptr);
+ sprintf(addr, "%16.16lx", (__u64)rptr);
#else
sprintf(addr, "%8.8X", (__u32)rptr);
#endif
@@ -164,7 +164,7 @@ void ctcmpc_dumpit(char *buf, int len)
strcat(bhex, " ");
#if (UTS_MACHINE == s390x)
- sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
+ sprintf(tbuf, "%2.2lX", (__u64)*ptr);
#else
sprintf(tbuf, "%2.2X", (__u32)*ptr);
#endif
@@ -179,24 +179,24 @@ void ctcmpc_dumpit(char *buf, int len)
basc[sw+1] = '\0';
sw++;
rm--;
- if (sw == 16) {
- if ((strcmp(duphex, bhex)) != 0) {
- if (dup != 0) {
- sprintf(tdup, "Duplicate as above "
- "to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
- }
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
+ if (sw != 16)
+ continue;
+ if ((strcmp(duphex, bhex)) != 0) {
+ if (dup != 0) {
+ sprintf(tdup,
+ "Duplicate as above to %s", addr);
+ ctcm_pr_debug(" --- %s ---\n",
+ tdup);
+ }
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
addr, boff, bhex, basc);
- dup = 0;
- strcpy(duphex, bhex);
- } else
- dup++;
+ dup = 0;
+ strcpy(duphex, bhex);
+ } else
+ dup++;
- sw = 0;
- rm = 16;
- }
+ sw = 0;
+ rm = 16;
} /* endfor */
if (sw != 0) {
@@ -210,19 +210,17 @@ void ctcmpc_dumpit(char *buf, int len)
}
if (dup != 0) {
sprintf(tdup, "Duplicate as above to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
+ ctcm_pr_debug(" --- %s ---\n", tdup);
}
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
- addr, boff, bhex, basc);
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
+ addr, boff, bhex, basc);
} else {
if (dup >= 1) {
sprintf(tdup, "Duplicate as above to %s", addr);
- printk(KERN_INFO " "
- " --- %s ---\n", tdup);
+ ctcm_pr_debug(" --- %s ---\n", tdup);
}
if (dup != 0) {
- printk(KERN_INFO " %s (+%s) : %s [%s]\n",
+ ctcm_pr_debug(" %s (+%s) : %s [%s]\n",
addr, boff, bhex, basc);
}
}
@@ -241,7 +239,7 @@ void ctcmpc_dumpit(char *buf, int len)
*/
void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
{
- unsigned char *p = skb->data;
+ __u8 *p = skb->data;
struct th_header *header;
struct pdu *pheader;
int bl = skb->len;
@@ -253,8 +251,8 @@ void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
p += offset;
header = (struct th_header *)p;
- printk(KERN_INFO "dump:\n");
- printk(KERN_INFO "skb len=%d \n", skb->len);
+ ctcm_pr_debug("dump:\n");
+ ctcm_pr_debug("skb len=%d \n", skb->len);
if (skb->len > 2) {
switch (header->th_ch_flag) {
case TH_HAS_PDU:
@@ -273,32 +271,64 @@ void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
}
pheader = (struct pdu *)p;
- printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
- pheader->pdu_offset, pheader->pdu_offset);
- printk(KERN_INFO "pdu->flag : %02x\n", pheader->pdu_flag);
- printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
- printk(KERN_INFO "pdu->seq : %02x\n", pheader->pdu_seq);
+ ctcm_pr_debug("pdu->offset: %d hex: %04x\n",
+ pheader->pdu_offset, pheader->pdu_offset);
+ ctcm_pr_debug("pdu->flag : %02x\n", pheader->pdu_flag);
+ ctcm_pr_debug("pdu->proto : %02x\n", pheader->pdu_proto);
+ ctcm_pr_debug("pdu->seq : %02x\n", pheader->pdu_seq);
goto dumpdata;
dumpth:
- printk(KERN_INFO "th->seg : %02x\n", header->th_seg);
- printk(KERN_INFO "th->ch : %02x\n", header->th_ch_flag);
- printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
- printk(KERN_INFO "th->type : %s\n",
- (header->th_is_xid) ? "DATA" : "XID");
- printk(KERN_INFO "th->seqnum : %04x\n", header->th_seq_num);
+ ctcm_pr_debug("th->seg : %02x\n", header->th_seg);
+ ctcm_pr_debug("th->ch : %02x\n", header->th_ch_flag);
+ ctcm_pr_debug("th->blk_flag: %02x\n", header->th_blk_flag);
+ ctcm_pr_debug("th->type : %s\n",
+ (header->th_is_xid) ? "DATA" : "XID");
+ ctcm_pr_debug("th->seqnum : %04x\n", header->th_seq_num);
}
dumpdata:
if (bl > 32)
bl = 32;
- printk(KERN_INFO "data: ");
+ ctcm_pr_debug("data: ");
for (i = 0; i < bl; i++)
- printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
- printk(KERN_INFO "\n");
+ ctcm_pr_debug("%02x%s", *p++, (i % 16) ? " " : "\n");
+ ctcm_pr_debug("\n");
}
#endif
+static struct net_device *ctcmpc_get_dev(int port_num)
+{
+ char device[20];
+ struct net_device *dev;
+ struct ctcm_priv *priv;
+
+ sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+
+ dev = __dev_get_by_name(&init_net, device);
+
+ if (dev == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s: Device not found by name: %s",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ priv = dev->priv;
+ if (priv == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): dev->priv is NULL",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ if (priv->mpcg == NULL) {
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): priv->mpcg is NULL",
+ CTCM_FUNTAIL, device);
+ return NULL;
+ }
+ return dev;
+}
+
/*
* ctc_mpc_alloc_channel
* (exported interface)
@@ -308,34 +338,23 @@ dumpdata:
*/
int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
{
- char device[20];
struct net_device *dev;
struct mpc_group *grp;
struct ctcm_priv *priv;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return 1;
- }
-
priv = dev->priv;
grp = priv->mpcg;
- if (!grp)
- return 1;
grp->allochanfunc = callback;
grp->port_num = port_num;
grp->port_persist = 1;
- ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
- __FUNCTION__,
- dev->name,
- fsm_getstate_str(grp->fsm));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "%s(%s): state=%s",
+ CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
switch (fsm_getstate(grp->fsm)) {
case MPCG_STATE_INOP:
@@ -377,12 +396,8 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
grp->allocchan_callback_retries = 0;
}
break;
- default:
- return 0;
-
}
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return 0;
}
EXPORT_SYMBOL(ctc_mpc_alloc_channel);
@@ -394,31 +409,22 @@ EXPORT_SYMBOL(ctc_mpc_alloc_channel);
void ctc_mpc_establish_connectivity(int port_num,
void (*callback)(int, int, int))
{
- char device[20];
struct net_device *dev;
struct mpc_group *grp;
struct ctcm_priv *priv;
struct channel *rch, *wch;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_establish_connectivity "
- "%s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return;
- }
priv = dev->priv;
+ grp = priv->mpcg;
rch = priv->channel[READ];
wch = priv->channel[WRITE];
- grp = priv->mpcg;
-
- ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
- __FUNCTION__, dev->name,
- fsm_getstate_str(grp->fsm));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "%s(%s): state=%s",
+ CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
grp->estconnfunc = callback;
grp->port_num = port_num;
@@ -446,8 +452,10 @@ void ctc_mpc_establish_connectivity(int port_num,
case MPCG_STATE_RESET:
/* MPC Group is not ready to start XID - min num of */
/* 1 read and 1 write channel have not been acquired*/
- printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
- "uest - Channel Pair is not Active\n", __FUNCTION__);
+
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): REJECTED - inactive channels",
+ CTCM_FUNTAIL, dev->name);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -457,11 +465,12 @@ void ctc_mpc_establish_connectivity(int port_num,
/* alloc channel was called but no XID exchange */
/* has occurred. initiate xside XID exchange */
/* make sure yside XID0 processing has not started */
+
if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
(fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
- printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
- " Request- PASSIVE XID in process\n"
- , __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): ABORT - PASSIVE XID",
+ CTCM_FUNTAIL, dev->name);
break;
}
grp->send_qllc_disc = 1;
@@ -476,9 +485,9 @@ void ctc_mpc_establish_connectivity(int port_num,
(fsm_getstate(rch->fsm) == CH_XID0_PENDING))
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
else {
- printk(KERN_WARNING "mpc: %s() Unable to start"
- " ACTIVE XID0 on read channel\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): RX-%s not ready for ACTIVE XID0",
+ CTCM_FUNTAIL, dev->name, rch->id);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -490,9 +499,9 @@ void ctc_mpc_establish_connectivity(int port_num,
(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
else {
- printk(KERN_WARNING "mpc: %s() Unable to start"
- " ACTIVE XID0 on write channel\n",
- __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): WX-%s not ready for ACTIVE XID0",
+ CTCM_FUNTAIL, dev->name, wch->id);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, -1, 0);
grp->estconnfunc = NULL;
@@ -508,7 +517,7 @@ void ctc_mpc_establish_connectivity(int port_num,
}
done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
+ CTCM_PR_DEBUG("Exit %s()\n", __func__);
return;
}
EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
@@ -520,40 +529,22 @@ EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
void ctc_mpc_dealloc_ch(int port_num)
{
struct net_device *dev;
- char device[20];
struct ctcm_priv *priv;
struct mpc_group *grp;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
- goto done;
- }
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
+ return;
+ priv = dev->priv;
+ grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
- dev->name, __FUNCTION__,
- dev->name, atomic_read(&dev->refcnt));
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
+ "%s: %s: refcount = %d\n",
+ CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() %s priv=NULL\n",
- __FUNCTION__, device);
- goto done;
- }
fsm_deltimer(&priv->restart_timer);
-
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
- goto done;
- }
grp->channels_terminating = 0;
-
fsm_deltimer(&grp->timer);
-
grp->allochanfunc = NULL;
grp->estconnfunc = NULL;
grp->port_persist = 0;
@@ -561,8 +552,6 @@ void ctc_mpc_dealloc_ch(int port_num)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
ctcm_close(dev);
-done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return;
}
EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
@@ -573,32 +562,22 @@ EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
*/
void ctc_mpc_flow_control(int port_num, int flowc)
{
- char device[20];
struct ctcm_priv *priv;
struct mpc_group *grp;
struct net_device *dev;
struct channel *rch;
int mpcg_state;
- ctcm_pr_debug("ctcmpc enter: %s() %i\n", __FUNCTION__, flowc);
-
- sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
- dev = __dev_get_by_name(&init_net, device);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
+ dev = ctcmpc_get_dev(port_num);
+ if (dev == NULL)
return;
- }
+ priv = dev->priv;
+ grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s: %s: flowc = %d",
+ CTCM_FUNTAIL, dev->name, flowc);
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
- __FUNCTION__, device);
- return;
- }
- grp = priv->mpcg;
rch = priv->channel[READ];
mpcg_state = fsm_getstate(grp->fsm);
@@ -629,7 +608,6 @@ void ctc_mpc_flow_control(int port_num, int flowc)
break;
}
- ctcm_pr_debug("ctcmpc exit: %s() %i\n", __FUNCTION__, flowc);
}
EXPORT_SYMBOL(ctc_mpc_flow_control);
@@ -646,12 +624,8 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo)
struct mpc_group *grp = priv->mpcg;
struct channel *ch = priv->channel[WRITE];
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
-
- if (do_debug_data)
- ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+ CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+ CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
grp->sweep_rsp_pend_num--;
@@ -684,14 +658,13 @@ static void ctcmpc_send_sweep_resp(struct channel *rch)
struct sk_buff *sweep_skb;
struct channel *ch = priv->channel[WRITE];
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, rch, rch->id);
+ CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id);
- sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
- GFP_ATOMIC|GFP_DMA);
+ sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
if (sweep_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc sweep_skb\n");
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): sweep_skb allocation ERROR\n",
+ CTCM_FUNTAIL, rch->id);
rc = -ENOMEM;
goto done;
}
@@ -746,7 +719,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
if (do_debug)
CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
- " %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
+ " %s(): ch=0x%p id=%s\n", __func__, ch, ch->id);
if (grp->in_sweep == 0) {
grp->in_sweep = 1;
@@ -755,8 +728,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo)
grp->sweep_rsp_pend_num = grp->active_channels[READ];
}
- if (do_debug_data)
- ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+ CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
grp->sweep_req_pend_num--;
ctcmpc_send_sweep_resp(ch);
@@ -875,25 +847,13 @@ static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm);
static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
{
struct net_device *dev = arg;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- return;
- }
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
return;
}
@@ -907,7 +867,12 @@ static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
grp->estconnfunc = NULL;
} else if (grp->allochanfunc)
grp->send_qllc_disc = 1;
- goto done;
+
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): fails",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
grp->port_persist = 1;
@@ -916,14 +881,7 @@ static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
tasklet_hi_schedule(&grp->mpc_tasklet2);
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
-
-done:
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
-
- ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
}
/*
@@ -933,42 +891,28 @@ done:
void mpc_group_ready(unsigned long adev)
{
struct net_device *dev = (struct net_device *)adev;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
struct channel *ch = NULL;
-
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- return;
- }
-
- grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
return;
}
- printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
- " maxbuf:%d\n",
- dev->name, grp->group_max_buflen);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+ "%s: %s: GROUP TRANSITIONED TO READY, maxbuf = %d\n",
+ CTCM_FUNTAIL, dev->name, grp->group_max_buflen);
fsm_newstate(grp->fsm, MPCG_STATE_READY);
/* Put up a read on the channel */
ch = priv->channel[READ];
ch->pdu_seq = 0;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
- __FUNCTION__, ch->pdu_seq);
+ CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
+ __func__, ch->pdu_seq);
ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
/* Put the write channel in idle state */
@@ -980,22 +924,18 @@ void mpc_group_ready(unsigned long adev)
spin_unlock(&ch->collect_lock);
}
ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
-
ctcm_clear_busy(dev);
if (grp->estconnfunc) {
grp->estconnfunc(grp->port_num, 0,
grp->group_max_buflen);
grp->estconnfunc = NULL;
- } else
- if (grp->allochanfunc)
- grp->allochanfunc(grp->port_num,
- grp->group_max_buflen);
+ } else if (grp->allochanfunc)
+ grp->allochanfunc(grp->port_num, grp->group_max_buflen);
grp->send_qllc_disc = 1;
grp->changed_side = 0;
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return;
}
@@ -1004,51 +944,26 @@ void mpc_group_ready(unsigned long adev)
* Increment the MPC Group Active Channel Counts
* helper of dev_action (called from channel fsm)
*/
-int mpc_channel_action(struct channel *ch, int direction, int action)
+void mpc_channel_action(struct channel *ch, int direction, int action)
{
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- int rc = 0;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
-
- if (dev == NULL) {
- printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
- action);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO
- "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
- action, dev->name);
- rc = 2;
- goto done;
- }
-
- grp = priv->mpcg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
- __FUNCTION__, action, dev->name);
- rc = 3;
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): No MPC group",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
- ctcm_pr_info(
- "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
- "active_channels read=%i, write=%i\n",
- __FUNCTION__,
- action,
- fsm_getstate_str(grp->fsm),
- grp->num_channel_paths,
- grp->active_channels[READ],
- grp->active_channels[WRITE]);
+ CTCM_PR_DEBUG("enter %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s: %i / Grp:%s total_channels=%i, active_channels: "
+ "read=%i, write=%i\n", __func__, action,
+ fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+ grp->active_channels[READ], grp->active_channels[WRITE]);
if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
grp->num_channel_paths++;
@@ -1062,10 +977,11 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
GFP_ATOMIC | GFP_DMA);
if (ch->xid_skb == NULL) {
- printk(KERN_INFO "ctcmpc: %s()"
- "Couldn't alloc ch xid_skb\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Couldn't alloc ch xid_skb\n",
+ CTCM_FUNTAIL, dev->name);
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
- return 1;
+ return;
}
ch->xid_skb_data = ch->xid_skb->data;
ch->xid_th = (struct th_header *)ch->xid_skb->data;
@@ -1097,8 +1013,9 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
(grp->active_channels[WRITE] > 0) &&
(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
- printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
- "CHANNELS ACTIVE\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+ "%s: %s: MPC GROUP CHANNELS ACTIVE\n",
+ __func__, dev->name);
}
} else if ((action == MPC_CHANNEL_REMOVE) &&
(ch->in_mpcgroup == 1)) {
@@ -1119,25 +1036,14 @@ int mpc_channel_action(struct channel *ch, int direction, int action)
(grp->active_channels[READ] > 0)))
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
-
done:
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "exit %s: %i / Grp:%s total_channels=%i, active_channels: "
+ "read=%i, write=%i\n", __func__, action,
+ fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+ grp->active_channels[READ], grp->active_channels[WRITE]);
- if (do_debug) {
- ctcm_pr_debug(
- "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
- "active_chans read=%i, write=%i\n",
- __FUNCTION__,
- action,
- fsm_getstate_str(grp->fsm),
- grp->num_channel_paths,
- grp->active_channels[READ],
- grp->active_channels[WRITE]);
-
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
- }
- return rc;
-
+ CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
}
/**
@@ -1163,9 +1069,8 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
int skblen;
int sendrc = 0;
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
- __FUNCTION__, dev->name, smp_processor_id(), ch->id);
+ CTCM_PR_DEBUG("ctcmpc enter: %s() %s cp:%i ch:%s\n",
+ __func__, dev->name, smp_processor_id(), ch->id);
header = (struct th_header *)pskb->data;
if ((header->th_seg == 0) &&
@@ -1174,21 +1079,16 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
(header->th_seq_num == 0))
/* nothing for us */ goto done;
- if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
- ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
- ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
- __FUNCTION__, pskb->len);
- }
+ CTCM_PR_DBGDATA("%s: th_header\n", __func__);
+ CTCM_D3_DUMP((char *)header, TH_HEADER_LENGTH);
+ CTCM_PR_DBGDATA("%s: pskb len: %04x \n", __func__, pskb->len);
pskb->dev = dev;
pskb->ip_summed = CHECKSUM_UNNECESSARY;
skb_pull(pskb, TH_HEADER_LENGTH);
if (likely(header->th_ch_flag == TH_HAS_PDU)) {
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
- __FUNCTION__);
+ CTCM_PR_DBGDATA("%s: came into th_has_pdu\n", __func__);
if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
(header->th_seq_num != ch->th_seq_num + 1) &&
@@ -1202,33 +1102,29 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
grp->out_of_sequence += 1;
__skb_push(pskb, TH_HEADER_LENGTH);
skb_queue_tail(&ch->io_queue, pskb);
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() th_seq_num "
- "expect:%08x got:%08x\n", __FUNCTION__,
- ch->th_seq_num + 1, header->th_seq_num);
+ CTCM_PR_DBGDATA("%s: th_seq_num expect:%08x "
+ "got:%08x\n", __func__,
+ ch->th_seq_num + 1, header->th_seq_num);
return;
}
grp->out_of_sequence = 0;
ch->th_seq_num = header->th_seq_num;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
- __FUNCTION__, ch->th_seq_num);
+ CTCM_PR_DBGDATA("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
+ __func__, ch->th_seq_num);
if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
goto done;
pdu_last_seen = 0;
while ((pskb->len > 0) && !pdu_last_seen) {
curr_pdu = (struct pdu *)pskb->data;
- if (do_debug_data) {
- ctcm_pr_debug("ctcm: %s() pdu_header\n",
- __FUNCTION__);
- ctcmpc_dumpit((char *)pskb->data,
- PDU_HEADER_LENGTH);
- ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
- __FUNCTION__, pskb->len);
- }
+
+ CTCM_PR_DBGDATA("%s: pdu_header\n", __func__);
+ CTCM_D3_DUMP((char *)pskb->data, PDU_HEADER_LENGTH);
+ CTCM_PR_DBGDATA("%s: pskb len: %04x \n",
+ __func__, pskb->len);
+
skb_pull(pskb, PDU_HEADER_LENGTH);
if (curr_pdu->pdu_flag & PDU_LAST)
@@ -1239,46 +1135,39 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
pskb->protocol = htons(ETH_P_SNA_DIX);
if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
- printk(KERN_INFO
- "%s Illegal packet size %d "
- "received "
- "dropping\n", dev->name,
- pskb->len);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Dropping packet with "
+ "illegal siize %d",
+ CTCM_FUNTAIL, dev->name, pskb->len);
+
priv->stats.rx_dropped++;
priv->stats.rx_length_errors++;
goto done;
}
skb_reset_mac_header(pskb);
new_len = curr_pdu->pdu_offset;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
- __FUNCTION__, new_len);
+ CTCM_PR_DBGDATA("%s: new_len: %04x \n",
+ __func__, new_len);
if ((new_len == 0) || (new_len > pskb->len)) {
/* should never happen */
/* pskb len must be hosed...bail out */
- printk(KERN_INFO
- "ctcmpc: %s(): invalid pdu"
- " offset of %04x - data may be"
- "lost\n", __FUNCTION__, new_len);
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): non valid pdu_offset: %04x",
+ /* "data may be lost", */
+ CTCM_FUNTAIL, dev->name, new_len);
+ goto done;
}
skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
if (!skb) {
- printk(KERN_INFO
- "ctcm: %s Out of memory in "
- "%s()- request-len:%04x \n",
- dev->name,
- __FUNCTION__,
- new_len+4);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): MEMORY allocation error",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
- fsm_event(grp->fsm,
- MPCG_EVENT_INOP, dev);
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
goto done;
}
-
- memcpy(skb_put(skb, new_len),
- pskb->data, new_len);
+ memcpy(skb_put(skb, new_len), pskb->data, new_len);
skb_reset_mac_header(skb);
skb->dev = pskb->dev;
@@ -1287,17 +1176,14 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
*((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
ch->pdu_seq++;
- if (do_debug_data)
- ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
- __FUNCTION__, ch->pdu_seq);
-
- ctcm_pr_debug("ctcm: %s() skb:%0lx "
- "skb len: %d \n", __FUNCTION__,
- (unsigned long)skb, skb->len);
if (do_debug_data) {
- ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
- " of pdu_data sent\n",
- __FUNCTION__);
+ ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
+ __func__, ch->pdu_seq);
+ ctcm_pr_debug("%s: skb:%0lx "
+ "skb len: %d \n", __func__,
+ (unsigned long)skb, skb->len);
+ ctcm_pr_debug("%s: up to 32 bytes "
+ "of pdu_data sent\n", __func__);
ctcmpc_dump32((char *)skb->data, skb->len);
}
@@ -1316,8 +1202,8 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
mpcginfo->ch = ch;
mpcginfo->th = header;
mpcginfo->skb = pskb;
- ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
- __FUNCTION__);
+ CTCM_PR_DEBUG("%s: Not PDU - may be control pkt\n",
+ __func__);
/* it's a sweep? */
sweep = (struct th_sweep *)pskb->data;
mpcginfo->sweep = sweep;
@@ -1333,8 +1219,9 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
} else if (header->th_blk_flag == TH_DISCONTACT)
fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
else if (header->th_seq_num != 0) {
- printk(KERN_INFO "%s unexpected packet"
- " expected control pkt\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): control pkt expected\n",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
/* mpcginfo only used for non-data transfers */
kfree(mpcginfo);
@@ -1347,13 +1234,12 @@ done:
dev_kfree_skb_any(pskb);
if (sendrc == NET_RX_DROP) {
printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
- " - PACKET DROPPED\n", dev->name, __FUNCTION__);
+ " - PACKET DROPPED\n", dev->name, __func__);
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+ __func__, dev->name, ch, ch->id);
}
/**
@@ -1366,15 +1252,14 @@ done:
*/
void ctcmpc_bh(unsigned long thischan)
{
- struct channel *ch = (struct channel *)thischan;
+ struct channel *ch = (struct channel *)thischan;
struct sk_buff *skb;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv = dev->priv;
- struct mpc_group *grp = priv->mpcg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- if (do_debug)
- ctcm_pr_debug("%s cp:%i enter: %s() %s\n",
- dev->name, smp_processor_id(), __FUNCTION__, ch->id);
+ CTCM_PR_DEBUG("%s cp:%i enter: %s() %s\n",
+ dev->name, smp_processor_id(), __func__, ch->id);
/* caller has requested driver to throttle back */
while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
(skb = skb_dequeue(&ch->io_queue))) {
@@ -1390,9 +1275,8 @@ void ctcmpc_bh(unsigned long thischan)
if (skb == skb_peek(&ch->io_queue))
break;
}
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
- dev->name, __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+ __func__, dev->name, ch, ch->id);
return;
}
@@ -1403,16 +1287,16 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
{
struct mpc_group *grp;
- CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+ "Enter %s(%p)", CTCM_FUNTAIL, priv);
grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
if (grp == NULL)
return NULL;
- grp->fsm =
- init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
- MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
- mpcg_fsm_len, GFP_KERNEL);
+ grp->fsm = init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
+ MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
+ mpcg_fsm_len, GFP_KERNEL);
if (grp->fsm == NULL) {
kfree(grp);
return NULL;
@@ -1424,7 +1308,6 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
grp->xid_skb =
__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
if (grp->xid_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
kfree_fsm(grp->fsm);
kfree(grp);
return NULL;
@@ -1435,7 +1318,7 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
&thnorm, TH_HEADER_LENGTH);
- grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
+ grp->xid = (struct xid2 *)skb_tail_pointer(grp->xid_skb);
memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
grp->xid->xid2_adj_id = jiffies | 0xfff00000;
grp->xid->xid2_sender_id = jiffies;
@@ -1446,7 +1329,6 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
grp->rcvd_xid_skb =
__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
if (grp->rcvd_xid_skb == NULL) {
- printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
kfree_fsm(grp->fsm);
dev_kfree_skb(grp->xid_skb);
kfree(grp);
@@ -1492,32 +1374,27 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
int rc = 0;
struct channel *wch, *rch;
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
- }
-
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
+ BUG_ON(dev == NULL);
+ CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name);
priv = dev->priv;
grp = priv->mpcg;
grp->flow_off_called = 0;
-
fsm_deltimer(&grp->timer);
-
if (grp->channels_terminating)
- goto done;
+ return;
grp->channels_terminating = 1;
-
grp->saved_state = fsm_getstate(grp->fsm);
fsm_newstate(grp->fsm, MPCG_STATE_INOP);
if (grp->saved_state > MPCG_STATE_XID7INITF)
- printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): MPC GROUP INOPERATIVE",
+ CTCM_FUNTAIL, dev->name);
if ((grp->saved_state != MPCG_STATE_RESET) ||
/* dealloc_channel has been called */
- ((grp->saved_state == MPCG_STATE_RESET) &&
- (grp->port_persist == 0)))
+ ((grp->saved_state == MPCG_STATE_RESET) &&
+ (grp->port_persist == 0)))
fsm_deltimer(&priv->restart_timer);
wch = priv->channel[WRITE];
@@ -1567,29 +1444,24 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
/* This can result in INOP of VTAM PU due to halting of */
/* outstanding IO which causes a sense to be returned */
/* Only about 3 senses are allowed and then IOS/VTAM will*/
- /* ebcome unreachable without manual intervention */
- if ((grp->port_persist == 1) || (grp->alloc_called)) {
+ /* become unreachable without manual intervention */
+ if ((grp->port_persist == 1) || (grp->alloc_called)) {
grp->alloc_called = 0;
fsm_deltimer(&priv->restart_timer);
- fsm_addtimer(&priv->restart_timer,
- 500,
- DEV_EVENT_RESTART,
- dev);
+ fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_RESTART, dev);
fsm_newstate(grp->fsm, MPCG_STATE_RESET);
if (grp->saved_state > MPCG_STATE_XID7INITF)
- printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+ "%s(%s): MPC GROUP RECOVERY SCHEDULED",
+ CTCM_FUNTAIL, dev->name);
} else {
fsm_deltimer(&priv->restart_timer);
fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
fsm_newstate(grp->fsm, MPCG_STATE_RESET);
- printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+ "%s(%s): NO MPC GROUP RECOVERY ATTEMPTED",
+ CTCM_FUNTAIL, dev->name);
}
-
-done:
- ctcm_pr_debug("ctcmpc exit:%s %s()\n", dev->name, __FUNCTION__);
- return;
}
/**
@@ -1609,12 +1481,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
struct channel *wch;
struct channel *rch;
- CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
-
- if (dev == NULL) {
- CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
- return;
- }
+ BUG_ON(dev == NULL);
priv = dev->priv;
grp = priv->mpcg;
@@ -1633,8 +1500,9 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
}
- CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
- __FUNCTION__, dev->name);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+ "%s: dev=%s exit",
+ CTCM_FUNTAIL, dev->name);
return;
}
@@ -1646,25 +1514,25 @@ void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
{
struct mpcg_info *mpcginfo = arg;
struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv = dev->priv;
- struct mpc_group *grp = priv->mpcg;
+ struct net_device *dev;
+ struct ctcm_priv *priv;
+ struct mpc_group *grp;
- if (ch == NULL) {
- printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
- return;
- }
- if (ch->netdev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- return;
+ if (ch) {
+ dev = ch->netdev;
+ if (dev) {
+ priv = dev->priv;
+ if (priv) {
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s: %s: %s\n",
+ CTCM_FUNTAIL, dev->name, ch->id);
+ grp = priv->mpcg;
+ grp->send_qllc_disc = 1;
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ }
+ }
}
- ctcm_pr_debug("ctcmpc enter: %s %s()\n", dev->name, __FUNCTION__);
-
- grp->send_qllc_disc = 1;
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1675,26 +1543,9 @@ void mpc_action_discontact(fsm_instance *fi, int event, void *arg)
*/
void mpc_action_send_discontact(unsigned long thischan)
{
- struct channel *ch;
- struct net_device *dev;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
- int rc = 0;
- unsigned long saveflags;
-
- ch = (struct channel *)thischan;
- dev = ch->netdev;
- priv = dev->priv;
- grp = priv->mpcg;
-
- ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
- dev->name,
- smp_processor_id(),
- __FUNCTION__,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- saveflags = 0; /* avoids compiler warning with
- spin_unlock_irqrestore */
+ int rc;
+ struct channel *ch = (struct channel *)thischan;
+ unsigned long saveflags = 0;
spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
rc = ccw_device_start(ch->cdev, &ch->ccw[15],
@@ -1702,16 +1553,9 @@ void mpc_action_send_discontact(unsigned long thischan)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) {
- ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
- __FUNCTION__,
- ch->id);
- ctcm_ccw_check_rc(ch, rc, "send discontact");
- /* Not checking return code value here */
- /* Making best effort to notify partner*/
- /* that MPC Group is going down */
+ ctcm_ccw_check_rc(ch, rc, (char *)__func__);
}
- ctcm_pr_debug("ctcmpc exit: %s %s()\n", dev->name, __FUNCTION__);
return;
}
@@ -1723,49 +1567,50 @@ void mpc_action_send_discontact(unsigned long thischan)
*/
static int mpc_validate_xid(struct mpcg_info *mpcginfo)
{
- struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
+ struct channel *ch = mpcginfo->ch;
+ struct net_device *dev = ch->netdev;
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- struct xid2 *xid = mpcginfo->xid;
- int failed = 0;
- int rc = 0;
- __u64 our_id, their_id = 0;
- int len;
-
- len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+ struct xid2 *xid = mpcginfo->xid;
+ int rc = 0;
+ __u64 our_id = 0;
+ __u64 their_id = 0;
+ int len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
+ CTCM_PR_DEBUG("Enter %s: xid=%p\n", __func__, xid);
- if (mpcginfo->xid == NULL) {
- printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
+ if (xid == NULL) {
rc = 1;
- goto done;
+ /* XID REJECTED: xid == NULL */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid = NULL",
+ CTCM_FUNTAIL, ch->id);
+ goto done;
}
- ctcm_pr_debug("ctcmpc : %s xid received()\n", __FUNCTION__);
- ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
+ CTCM_D3_DUMP((char *)xid, XID2_LENGTH);
/*the received direction should be the opposite of ours */
if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
XID2_READ_SIDE) != xid->xid2_dlc_type) {
- failed = 1;
- printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
- "Pairing Invalid \n", __FUNCTION__);
+ rc = 2;
+ /* XID REJECTED: r/w channel pairing mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): r/w channel pairing mismatch",
+ CTCM_FUNTAIL, ch->id);
+ goto done;
}
if (xid->xid2_dlc_type == XID2_READ_SIDE) {
- ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
- __FUNCTION__, grp->group_max_buflen,
- xid->xid2_buf_len);
+ CTCM_PR_DEBUG("%s: grpmaxbuf:%d xid2buflen:%d\n", __func__,
+ grp->group_max_buflen, xid->xid2_buf_len);
- if (grp->group_max_buflen == 0 ||
- grp->group_max_buflen > xid->xid2_buf_len - len)
+ if (grp->group_max_buflen == 0 || grp->group_max_buflen >
+ xid->xid2_buf_len - len)
grp->group_max_buflen = xid->xid2_buf_len - len;
}
-
- if (grp->saved_xid2 == NULL) {
+ if (grp->saved_xid2 == NULL) {
grp->saved_xid2 =
(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
@@ -1786,49 +1631,54 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
/* lower id assume the xside role */
if (our_id < their_id) {
grp->roll = XSIDE;
- ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
- "TAKE XSIDE\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): WE HAVE LOW ID - TAKE XSIDE",
+ CTCM_FUNTAIL, ch->id);
} else {
grp->roll = YSIDE;
- ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
- "TAKE YSIDE\n", __FUNCTION__);
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+ "%s(%s): WE HAVE HIGH ID - TAKE YSIDE",
+ CTCM_FUNTAIL, ch->id);
}
} else {
if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
- __FUNCTION__);
+ rc = 3;
+ /* XID REJECTED: xid flag byte4 mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid flag byte4 mismatch",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_flag2 == 0x40) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
- __FUNCTION__);
+ rc = 4;
+ /* XID REJECTED - xid NOGOOD */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): xid NOGOOD",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - "
- "Adjacent Station ID Mismatch\n",
- __FUNCTION__);
+ rc = 5;
+ /* XID REJECTED - Adjacent Station ID Mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Adjacent Station ID Mismatch",
+ CTCM_FUNTAIL, ch->id);
}
if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
- failed = 1;
- printk(KERN_INFO "%s XID REJECTED - "
- "Sender Address Mismatch\n", __FUNCTION__);
-
+ rc = 6;
+ /* XID REJECTED - Sender Address Mismatch */
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): Sender Address Mismatch",
+ CTCM_FUNTAIL, ch->id);
}
}
- if (failed) {
+done:
+ if (rc) {
ctcm_pr_info("ctcmpc : %s() failed\n", __FUNCTION__);
priv->xid->xid2_flag2 = 0x40;
grp->saved_xid2->xid2_flag2 = 0x40;
- rc = 1;
}
-done:
-
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
return rc;
}
@@ -1839,46 +1689,20 @@ done:
static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
{
struct channel *ch = arg;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- struct net_device *dev = NULL;
int rc = 0;
int gotlock = 0;
unsigned long saveflags = 0; /* avoids compiler warning with
- spin_unlock_irqrestore */
-
- if (ch == NULL) {
- printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
- goto done;
- }
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- dev = ch->netdev;
- if (dev == NULL) {
- printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
- goto done;
- }
+ spin_unlock_irqrestore */
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
- goto done;
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
if (ctcm_checkalloc_buffer(ch))
goto done;
- /* skb data-buffer referencing: */
-
+ /*
+ * skb data-buffer referencing:
+ */
ch->trans_skb->data = ch->trans_skb_data;
skb_reset_tail_pointer(ch->trans_skb);
ch->trans_skb->len = 0;
@@ -1911,22 +1735,22 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[8].count = 0;
ch->ccw[8].cda = 0x00;
+ if (!(ch->xid_th && ch->xid && ch->xid_id))
+ CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+ "%s(%s): xid_th=%p, xid=%p, xid_id=%p",
+ CTCM_FUNTAIL, ch->id, ch->xid_th, ch->xid, ch->xid_id);
+
if (side == XSIDE) {
/* mpc_action_xside_xid */
- if (ch->xid_th == NULL) {
- printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_th == NULL)
+ goto done;
ch->ccw[9].cmd_code = CCW_CMD_WRITE;
ch->ccw[9].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[9].count = TH_HEADER_LENGTH;
ch->ccw[9].cda = virt_to_phys(ch->xid_th);
- if (ch->xid == NULL) {
- printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
- goto done;
- }
-
+ if (ch->xid == NULL)
+ goto done;
ch->ccw[10].cmd_code = CCW_CMD_WRITE;
ch->ccw[10].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[10].count = XID2_LENGTH;
@@ -1956,28 +1780,22 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[10].count = XID2_LENGTH;
ch->ccw[10].cda = virt_to_phys(ch->rcvd_xid);
- if (ch->xid_th == NULL) {
- printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_th == NULL)
+ goto done;
ch->ccw[11].cmd_code = CCW_CMD_WRITE;
ch->ccw[11].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[11].count = TH_HEADER_LENGTH;
ch->ccw[11].cda = virt_to_phys(ch->xid_th);
- if (ch->xid == NULL) {
- printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid == NULL)
+ goto done;
ch->ccw[12].cmd_code = CCW_CMD_WRITE;
ch->ccw[12].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
ch->ccw[12].count = XID2_LENGTH;
ch->ccw[12].cda = virt_to_phys(ch->xid);
- if (ch->xid_id == NULL) {
- printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
- goto done;
- }
+ if (ch->xid_id == NULL)
+ goto done;
ch->ccw[13].cmd_code = CCW_CMD_WRITE;
ch->ccw[13].cda = virt_to_phys(ch->xid_id);
@@ -1990,12 +1808,11 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
ch->ccw[14].count = 0;
ch->ccw[14].cda = 0;
- if (do_debug_ccw)
- ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+ CTCM_CCW_DUMP((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+ CTCM_D3_DUMP((char *)ch->xid_th, TH_HEADER_LENGTH);
+ CTCM_D3_DUMP((char *)ch->xid, XID2_LENGTH);
+ CTCM_D3_DUMP((char *)ch->xid_id, 4);
- ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
- ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
- ctcmpc_dumpit((char *)ch->xid_id, 4);
if (!in_irq()) {
/* Such conditional locking is a known problem for
* sparse because its static undeterministic.
@@ -2012,16 +1829,13 @@ static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
if (rc != 0) {
- ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
- __FUNCTION__, ch->id);
ctcm_ccw_check_rc(ch, rc,
(side == XSIDE) ? "x-side XID" : "y-side XID");
}
done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
+ CTCM_PR_DEBUG("Exit %s: ch=0x%p id=%s\n",
+ __func__, ch, ch->id);
return;
}
@@ -2050,41 +1864,19 @@ static void mpc_action_yside_xid(fsm_instance *fsm, int event, void *arg)
*/
static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
{
- struct channel *ch = arg;
- struct ctcm_priv *priv;
- struct mpc_group *grp = NULL;
- struct net_device *dev = NULL;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- if (ch == NULL) {
- printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
- goto done;
- }
-
- dev = ch->netdev;
- if (dev == NULL) {
- printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
- goto done;
- }
+ struct channel *ch = arg;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
- goto done;
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
if (ch->xid == NULL) {
- printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): ch->xid == NULL",
+ CTCM_FUNTAIL, dev->name);
+ return;
}
fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
@@ -2104,12 +1896,7 @@ static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
-done:
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
- __FUNCTION__, ch, ch->id);
return;
-
}
/*
@@ -2119,32 +1906,16 @@ done:
static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
{
struct net_device *dev = arg;
- struct ctcm_priv *priv = NULL;
- struct mpc_group *grp = NULL;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = NULL;
int direction;
- int rc = 0;
int send = 0;
- ctcm_pr_debug("ctcmpc enter: %s() \n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- grp = priv->mpcg;
+ if (priv)
+ grp = priv->mpcg;
if (grp == NULL) {
- printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
- rc = 1;
- goto done;
+ fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+ return;
}
for (direction = READ; direction <= WRITE; direction++) {
@@ -2199,11 +1970,6 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
}
-done:
-
- if (rc != 0)
- fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
return;
}
@@ -2214,24 +1980,15 @@ done:
static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
{
- struct mpcg_info *mpcginfo = arg;
- struct channel *ch = mpcginfo->ch;
- struct net_device *dev = ch->netdev;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- priv = dev->priv;
- grp = priv->mpcg;
+ struct mpcg_info *mpcginfo = arg;
+ struct channel *ch = mpcginfo->ch;
+ struct net_device *dev = ch->netdev;
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
- __FUNCTION__, ch->id,
- grp->outstanding_xid2,
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
+ CTCM_PR_DEBUG("%s: ch-id:%s xid2:%i xid7:%i xidt_p2:%i \n",
+ __func__, ch->id, grp->outstanding_xid2,
+ grp->outstanding_xid7, grp->outstanding_xid7_p2);
if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
fsm_newstate(ch->fsm, CH_XID7_PENDING);
@@ -2268,17 +2025,12 @@ static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
}
kfree(mpcginfo);
- if (do_debug) {
- ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
- __FUNCTION__, ch->id,
- grp->outstanding_xid2,
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
- ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
- __FUNCTION__, ch->id,
- fsm_getstate_str(grp->fsm),
- fsm_getstate_str(ch->fsm));
- }
+ CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+ __func__, ch->id, grp->outstanding_xid2,
+ grp->outstanding_xid7, grp->outstanding_xid7_p2);
+ CTCM_PR_DEBUG("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
+ __func__, ch->id,
+ fsm_getstate_str(grp->fsm), fsm_getstate_str(ch->fsm));
return;
}
@@ -2296,15 +2048,10 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
struct ctcm_priv *priv = dev->priv;
struct mpc_group *grp = priv->mpcg;
- if (do_debug) {
- ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
-
- ctcm_pr_debug("ctcmpc: outstanding_xid7: %i, "
- " outstanding_xid7_p2: %i\n",
- grp->outstanding_xid7,
- grp->outstanding_xid7_p2);
- }
+ CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+ __func__, smp_processor_id(), ch, ch->id);
+ CTCM_PR_DEBUG("%s: outstanding_xid7: %i, outstanding_xid7_p2: %i\n",
+ __func__, grp->outstanding_xid7, grp->outstanding_xid7_p2);
grp->outstanding_xid7--;
ch->xid_skb->data = ch->xid_skb_data;
@@ -2337,14 +2084,8 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
mpc_validate_xid(mpcginfo);
break;
}
-
kfree(mpcginfo);
-
- if (do_debug)
- ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
- __FUNCTION__, smp_processor_id(), ch, ch->id);
return;
-
}
/*
@@ -2353,36 +2094,14 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg)
*/
static int mpc_send_qllc_discontact(struct net_device *dev)
{
- int rc = 0;
__u32 new_len = 0;
struct sk_buff *skb;
struct qllc *qllcptr;
- struct ctcm_priv *priv;
- struct mpc_group *grp;
-
- ctcm_pr_debug("ctcmpc enter: %s()\n", __FUNCTION__);
-
- if (dev == NULL) {
- printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
-
- priv = dev->priv;
- if (priv == NULL) {
- printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
+ struct ctcm_priv *priv = dev->priv;
+ struct mpc_group *grp = priv->mpcg;
- grp = priv->mpcg;
- if (grp == NULL) {
- printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
- rc = 1;
- goto done;
- }
- ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
- mpcg_state_names[grp->saved_state]);
+ CTCM_PR_DEBUG("%s: GROUP STATE: %s\n",
+ __func__, mpcg_state_names[grp->saved_state]);
switch (grp->saved_state) {
/*
@@ -2408,11 +2127,10 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
new_len = sizeof(struct qllc);
qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
if (qllcptr == NULL) {
- printk(KERN_INFO
- "ctcmpc: Out of memory in %s()\n",
- dev->name);
- rc = 1;
- goto done;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): qllcptr allocation error",
+ CTCM_FUNTAIL, dev->name);
+ return -ENOMEM;
}
qllcptr->qllc_address = 0xcc;
@@ -2421,31 +2139,29 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
if (skb == NULL) {
- printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
- dev->name);
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): skb allocation error",
+ CTCM_FUNTAIL, dev->name);
priv->stats.rx_dropped++;
- rc = 1;
kfree(qllcptr);
- goto done;
+ return -ENOMEM;
}
memcpy(skb_put(skb, new_len), qllcptr, new_len);
kfree(qllcptr);
if (skb_headroom(skb) < 4) {
- printk(KERN_INFO "ctcmpc: %s() Unable to"
- " build discontact for %s\n",
- __FUNCTION__, dev->name);
- rc = 1;
+ CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+ "%s(%s): skb_headroom error",
+ CTCM_FUNTAIL, dev->name);
dev_kfree_skb_any(skb);
- goto done;
+ return -ENOMEM;
}
*((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
priv->channel[READ]->pdu_seq++;
- if (do_debug_data)
- ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
- __FUNCTION__, priv->channel[READ]->pdu_seq);
+ CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
+ __func__, priv->channel[READ]->pdu_seq);
/* receipt of CC03 resets anticipated sequence number on
receiving side */
@@ -2455,7 +2171,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
skb->protocol = htons(ETH_P_SNAP);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
+ CTCM_D3_DUMP(skb->data, (sizeof(struct qllc) + 4));
netif_rx(skb);
break;
@@ -2464,9 +2180,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
}
-done:
- ctcm_pr_debug("ctcmpc exit: %s()\n", __FUNCTION__);
- return rc;
+ return 0;
}
/* --- This is the END my friend --- */
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index f99686069a9..5336120cddf 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -231,7 +231,7 @@ static inline void ctcmpc_dump32(char *buf, int len)
int ctcmpc_open(struct net_device *);
void ctcm_ccw_check_rc(struct channel *, int, char *);
void mpc_group_ready(unsigned long adev);
-int mpc_channel_action(struct channel *ch, int direction, int action);
+void mpc_channel_action(struct channel *ch, int direction, int action);
void mpc_action_send_discontact(unsigned long thischan);
void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
void ctcmpc_bh(unsigned long thischan);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b29afef5c7f..38de31b5570 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2651,7 +2651,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
tag = (u16 *)(new_skb->data + 12);
*tag = __constant_htons(ETH_P_8021Q);
*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
- VLAN_TX_SKB_CB(new_skb)->magic = 0;
+ new_skb->vlan_tci = 0;
}
}
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 513ba61ae96..777637594ac 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -195,8 +195,8 @@ struct uctrl_driver {
static struct uctrl_driver drv;
-void uctrl_get_event_status(void);
-void uctrl_get_external_status(void);
+static void uctrl_get_event_status(void);
+static void uctrl_get_external_status(void);
static int
uctrl_ioctl(struct inode *inode, struct file *file,
@@ -266,12 +266,6 @@ static struct miscdevice uctrl_dev = {
driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \
}
-void uctrl_set_video(int status)
-{
- struct uctrl_driver *driver = &drv;
-
-}
-
static void uctrl_do_txn(struct uctrl_txn *txn)
{
struct uctrl_driver *driver = &drv;
@@ -311,7 +305,7 @@ static void uctrl_do_txn(struct uctrl_txn *txn)
}
}
-void uctrl_get_event_status(void)
+static void uctrl_get_event_status(void)
{
struct uctrl_driver *driver = &drv;
struct uctrl_txn txn;
@@ -331,7 +325,7 @@ void uctrl_get_event_status(void)
dprintk(("ev is %x\n", driver->status.event_status));
}
-void uctrl_get_external_status(void)
+static void uctrl_get_external_status(void)
{
struct uctrl_driver *driver = &drv;
struct uctrl_txn txn;
@@ -363,7 +357,7 @@ void uctrl_get_external_status(void)
static int __init ts102_uctrl_init(void)
{
struct uctrl_driver *driver = &drv;
- int len, i;
+ int len;
struct linux_prom_irqs tmp_irq[2];
unsigned int vaddr[2] = { 0, 0 };
int tmpnode, uctrlnode = prom_getchild(prom_root_node);
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
index f1aa1389ea4..a5240c52aa0 100644
--- a/drivers/sbus/char/vfc.h
+++ b/drivers/sbus/char/vfc.h
@@ -133,8 +133,6 @@ struct vfc_dev {
unsigned char saa9051_state_array[VFC_SAA9051_NR];
};
-extern struct vfc_dev **vfc_dev_lst;
-
void captstat_reset(struct vfc_dev *);
void memptr_reset(struct vfc_dev *);
@@ -145,8 +143,6 @@ int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ;
int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ;
int vfc_i2c_reset_bus(struct vfc_dev *);
int vfc_init_i2c_bus(struct vfc_dev *);
-void vfc_lock_device(struct vfc_dev *);
-void vfc_unlock_device(struct vfc_dev *);
#define VFC_CONTROL_DIAGMODE 0x10000000
#define VFC_CONTROL_MEMPTR 0x20000000
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 1f6cb8ae278..25181bb7d62 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -45,7 +45,7 @@
#include <asm/vfc_ioctls.h>
static const struct file_operations vfc_fops;
-struct vfc_dev **vfc_dev_lst;
+static struct vfc_dev **vfc_dev_lst;
static char vfcstr[]="vfc";
static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
0x00, 0x64, 0x72, 0x52,
@@ -54,18 +54,18 @@ static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
0x3e
};
-void vfc_lock_device(struct vfc_dev *dev)
+static void vfc_lock_device(struct vfc_dev *dev)
{
mutex_lock(&dev->device_lock_mtx);
}
-void vfc_unlock_device(struct vfc_dev *dev)
+static void vfc_unlock_device(struct vfc_dev *dev)
{
mutex_unlock(&dev->device_lock_mtx);
}
-void vfc_captstat_reset(struct vfc_dev *dev)
+static void vfc_captstat_reset(struct vfc_dev *dev)
{
dev->control_reg |= VFC_CONTROL_CAPTRESET;
sbus_writel(dev->control_reg, &dev->regs->control);
@@ -75,7 +75,7 @@ void vfc_captstat_reset(struct vfc_dev *dev)
sbus_writel(dev->control_reg, &dev->regs->control);
}
-void vfc_memptr_reset(struct vfc_dev *dev)
+static void vfc_memptr_reset(struct vfc_dev *dev)
{
dev->control_reg |= VFC_CONTROL_MEMPTR;
sbus_writel(dev->control_reg, &dev->regs->control);
@@ -85,7 +85,7 @@ void vfc_memptr_reset(struct vfc_dev *dev)
sbus_writel(dev->control_reg, &dev->regs->control);
}
-int vfc_csr_init(struct vfc_dev *dev)
+static int vfc_csr_init(struct vfc_dev *dev)
{
dev->control_reg = 0x80000000;
sbus_writel(dev->control_reg, &dev->regs->control);
@@ -107,7 +107,7 @@ int vfc_csr_init(struct vfc_dev *dev)
return 0;
}
-int vfc_saa9051_init(struct vfc_dev *dev)
+static int vfc_saa9051_init(struct vfc_dev *dev)
{
int i;
@@ -119,7 +119,7 @@ int vfc_saa9051_init(struct vfc_dev *dev)
return 0;
}
-int init_vfc_hw(struct vfc_dev *dev)
+static int init_vfc_hw(struct vfc_dev *dev)
{
vfc_lock_device(dev);
vfc_csr_init(dev);
@@ -132,7 +132,7 @@ int init_vfc_hw(struct vfc_dev *dev)
return 0;
}
-int init_vfc_devstruct(struct vfc_dev *dev, int instance)
+static int init_vfc_devstruct(struct vfc_dev *dev, int instance)
{
dev->instance=instance;
mutex_init(&dev->device_lock_mtx);
@@ -141,7 +141,8 @@ int init_vfc_devstruct(struct vfc_dev *dev, int instance)
return 0;
}
-int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
+static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev,
+ int instance)
{
if(dev == NULL) {
printk(KERN_ERR "VFC: Bogus pointer passed\n");
@@ -168,7 +169,7 @@ int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
}
-struct vfc_dev *vfc_get_dev_ptr(int instance)
+static struct vfc_dev *vfc_get_dev_ptr(int instance)
{
return vfc_dev_lst[instance];
}
@@ -292,7 +293,7 @@ static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp)
return 0;
}
-int vfc_capture_start(struct vfc_dev *dev)
+static int vfc_capture_start(struct vfc_dev *dev)
{
vfc_captstat_reset(dev);
dev->control_reg = sbus_readl(&dev->regs->control);
@@ -314,7 +315,7 @@ int vfc_capture_start(struct vfc_dev *dev)
return 0;
}
-int vfc_capture_poll(struct vfc_dev *dev)
+static int vfc_capture_poll(struct vfc_dev *dev)
{
int timeout = 1000;
@@ -390,8 +391,8 @@ static int vfc_set_control_ioctl(struct inode *inode, struct file *file,
}
-int vfc_port_change_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
+static int vfc_port_change_ioctl(struct inode *inode, struct file *file,
+ struct vfc_dev *dev, unsigned long arg)
{
int ret = 0;
int cmd;
@@ -460,8 +461,8 @@ int vfc_port_change_ioctl(struct inode *inode, struct file *file,
return ret;
}
-int vfc_set_video_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
+static int vfc_set_video_ioctl(struct inode *inode, struct file *file,
+ struct vfc_dev *dev, unsigned long arg)
{
int ret = 0;
int cmd;
@@ -511,8 +512,8 @@ int vfc_set_video_ioctl(struct inode *inode, struct file *file,
return ret;
}
-int vfc_get_video_ioctl(struct inode *inode, struct file *file,
- struct vfc_dev *dev, unsigned long arg)
+static int vfc_get_video_ioctl(struct inode *inode, struct file *file,
+ struct vfc_dev *dev, unsigned long arg)
{
int ret = 0;
unsigned int status = NO_LOCK;
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 9efed771f6c..32b986e0ed7 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -114,7 +114,7 @@ int vfc_i2c_reset_bus(struct vfc_dev *dev)
return 0;
}
-int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
+static int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
{
int timeout = 1000;
@@ -126,7 +126,7 @@ int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
return 0;
}
-int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
+static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
{
int timeout = 1000;
int s1;
@@ -144,7 +144,8 @@ int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
}
#define SHIFT(a) ((a) << 24)
-int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode)
+static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr,
+ char mode)
{
int ret, raddr;
#if 1
@@ -195,7 +196,7 @@ int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode)
return 0;
}
-int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
+static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
{
int ret;
u32 val = SHIFT((unsigned int)*byte);
@@ -218,7 +219,8 @@ int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
return ret;
}
-int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last)
+static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte,
+ int last)
{
int ret;
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c
index 57e1526746a..ab0d2de3324 100644
--- a/drivers/sbus/dvma.c
+++ b/drivers/sbus/dvma.c
@@ -16,7 +16,7 @@
struct sbus_dma *dma_chain;
-void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
+static void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
{
printk("dma%d: ", num_dma);
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index c37d7c2587f..73a86d09bba 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -78,7 +78,7 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde
else
sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
sdev->ofdev.dev.bus = &sbus_bus_type;
- sprintf(sdev->ofdev.dev.bus_id, "sbus[%08x]", dp->node);
+ dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node);
if (of_device_register(&sdev->ofdev) != 0)
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
@@ -257,11 +257,11 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus)
sbus->ofdev.node = dp;
sbus->ofdev.dev.parent = NULL;
sbus->ofdev.dev.bus = &sbus_bus_type;
- sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
+ dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus);
if (of_device_register(&sbus->ofdev) != 0)
printk(KERN_DEBUG "sbus: device registration error for %s!\n",
- sbus->ofdev.dev.bus_id);
+ dev_name(&sbus->ofdev.dev));
dev_dp = dp->child;
while (dev_dp) {
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 2bc30e32b67..1fe0901e811 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -271,8 +271,8 @@ rebuild_sys_tab:
pHba->initialized = TRUE;
pHba->state &= ~DPTI_STATE_RESET;
if (adpt_sysfs_class) {
- struct device *dev = device_create(adpt_sysfs_class,
- NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit),
+ struct device *dev = device_create_drvdata(adpt_sysfs_class,
+ NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
"dpti%d", pHba->unit);
if (IS_ERR(dev)) {
printk(KERN_WARNING"dpti%d: unable to "
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 35cd892dce0..fed0b02ebc1 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -232,8 +232,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
}
if (shost->transportt->create_work_queue) {
- snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
- shost->host_no);
+ snprintf(shost->work_q_name, sizeof(shost->work_q_name),
+ "scsi_wq_%d", shost->host_no);
shost->work_q = create_singlethread_workqueue(
shost->work_q_name);
if (!shost->work_q) {
@@ -466,7 +466,8 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
struct device *cdev;
struct Scsi_Host *shost = ERR_PTR(-ENXIO);
- cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+ cdev = class_find_device(&shost_class, NULL, &hostnum,
+ __scsi_host_match);
if (cdev) {
shost = scsi_host_get(class_to_shost(cdev));
put_device(cdev);
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f843c1383a4..538552495d4 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -84,7 +84,6 @@ typedef struct ide_scsi_obj {
struct Scsi_Host *host;
struct ide_atapi_pc *pc; /* Current packet command */
- unsigned long flags; /* Status/Action flags */
unsigned long transform; /* SCSI cmd translation layer */
unsigned long log; /* log flags */
} idescsi_scsi_t;
@@ -126,23 +125,14 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
}
/*
- * Per ATAPI device status bits.
- */
-#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */
-
-/*
- * ide-scsi requests.
- */
-#define IDESCSI_PC_RQ 90
-
-/*
* PIO data transfer routine using the scatter gather table.
*/
static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write)
{
ide_hwif_t *hwif = drive->hwif;
- xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
char *buf;
int count;
@@ -228,7 +218,6 @@ static int idescsi_check_condition(ide_drive_t *drive,
rq->cmd_type = REQ_TYPE_SENSE;
rq->cmd_flags |= REQ_PREEMPT;
pc->timeout = jiffies + WAIT_READY;
- pc->callback = ide_scsi_callback;
/* NOTE! Save the failed packet command in "rq->buffer" */
rq->buffer = (void *) failed_cmd->special;
pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
@@ -237,6 +226,7 @@ static int idescsi_check_condition(ide_drive_t *drive,
ide_scsi_hex_dump(pc->c, 6);
}
rq->rq_disk = scsi->disk;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
return 0;
}
@@ -246,10 +236,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
/* force an abort */
- hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
rq->errors++;
@@ -421,10 +410,6 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
if (blk_sense_request(rq) || blk_special_request(rq)) {
struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
- if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags))
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
if (drive->using_dma && !idescsi_map_sg(drive, pc))
pc->flags |= PC_FLAG_DMA_OK;
@@ -460,11 +445,14 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
if (drive->id && (drive->id->config & 0x0060) == 0x20)
- set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+ set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
+
+ drive->pc_callback = ide_scsi_callback;
+
idescsi_add_settings(drive);
}
@@ -616,7 +604,6 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
pc->scsi_cmd = cmd;
pc->done = done;
pc->timeout = jiffies + cmd->timeout_per_command;
- pc->callback = ide_scsi_callback;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -631,6 +618,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
rq->special = (char *) pc;
rq->cmd_type = REQ_TYPE_SPECIAL;
spin_unlock_irq(host->host_lock);
+ memcpy(rq->cmd, pc->c, 12);
blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
spin_lock_irq(host->host_lock);
return 0;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 5fd64e70029..a272b9a2c86 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -417,15 +417,16 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host->next_vport_number = 0;
fc_host->npiv_vports_inuse = 0;
- snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
- shost->host_no);
+ snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name),
+ "fc_wq_%d", shost->host_no);
fc_host->work_q = create_singlethread_workqueue(
fc_host->work_q_name);
if (!fc_host->work_q)
return -ENOMEM;
- snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
- shost->host_no);
+ snprintf(fc_host->devloss_work_q_name,
+ sizeof(fc_host->devloss_work_q_name),
+ "fc_dl_%d", shost->host_no);
fc_host->devloss_work_q = create_singlethread_workqueue(
fc_host->devloss_work_q_name);
if (!fc_host->devloss_work_q) {
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3af7cbcc5c5..043c3921164 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -170,7 +170,7 @@ iscsi_create_endpoint(int dd_size)
int err;
for (id = 1; id < ISCSI_MAX_EPID; id++) {
- dev = class_find_device(&iscsi_endpoint_class, &id,
+ dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
iscsi_match_epid);
if (!dev)
break;
@@ -222,7 +222,7 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
struct iscsi_endpoint *ep;
struct device *dev;
- dev = class_find_device(&iscsi_endpoint_class, &handle,
+ dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
iscsi_match_epid);
if (!dev)
return NULL;
@@ -247,8 +247,8 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
atomic_set(&ihost->nr_scans, 0);
mutex_init(&ihost->mutex);
- snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
- shost->host_no);
+ snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name),
+ "iscsi_scan_%d", shost->host_no);
ihost->scan_workq = create_singlethread_workqueue(
ihost->scan_workq_name);
if (!ihost->scan_workq)
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index 2c87db98cdf..f9cf7015136 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <asm/irq.h>
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ce948b66bbd..a97f1ae11f7 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1293,7 +1293,18 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
char flag;
do {
- ch = serial_inp(up, UART_RX);
+ if (likely(lsr & UART_LSR_DR))
+ ch = serial_inp(up, UART_RX);
+ else
+ /*
+ * Intel 82571 has a Serial Over Lan device that will
+ * set UART_LSR_BI without setting UART_LSR_DR when
+ * it receives a break. To avoid reading from the
+ * receive buffer without UART_LSR_DR bit set, we
+ * just force the read character to be 0
+ */
+ ch = 0;
+
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1342,7 +1353,7 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
ignore_char:
lsr = serial_inp(up, UART_LSR);
- } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
@@ -1425,7 +1436,7 @@ serial8250_handle_port(struct uart_8250_port *up)
DEBUG_INTR("status = %x...", status);
- if (status & UART_LSR_DR)
+ if (status & (UART_LSR_DR | UART_LSR_BI))
receive_chars(up, &status);
check_modem_status(up);
if (status & UART_LSR_THRE)
@@ -1874,7 +1885,9 @@ static int serial8250_startup(struct uart_port *port)
* the interrupt is enabled. Delays are necessary to
* allow register changes to become visible.
*/
- spin_lock_irqsave(&up->port.lock, flags);
+ spin_lock(&up->port.lock);
+ if (up->port.flags & UPF_SHARE_IRQ)
+ disable_irq_nosync(up->port.irq);
wait_for_xmitr(up, UART_LSR_THRE);
serial_out_sync(up, UART_IER, UART_IER_THRI);
@@ -1886,7 +1899,9 @@ static int serial8250_startup(struct uart_port *port)
iir = serial_in(up, UART_IIR);
serial_out(up, UART_IER, 0);
- spin_unlock_irqrestore(&up->port.lock, flags);
+ if (up->port.flags & UPF_SHARE_IRQ)
+ enable_irq(up->port.irq);
+ spin_unlock(&up->port.lock);
/*
* If the interrupt is not reasserted, setup a timer to
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c
index 4eb7437a404..0416ad3bc12 100644
--- a/drivers/serial/8250_gsc.c
+++ b/drivers/serial/8250_gsc.c
@@ -119,3 +119,5 @@ int __init probe_serial_gsc(void)
}
module_init(probe_serial_gsc);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 1b36087665a..c2f23933155 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -767,6 +767,9 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
+/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
+
/*
* Master list of serial port init/setup/exit quirks.
* This does not describe the general nature of the port.
@@ -882,6 +885,15 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
},
{
.vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9050,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
+ .init = pci_plx9050_init,
+ .setup = pci_default_setup,
+ .exit = __devexit_p(pci_plx9050_exit),
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_ROMULUS,
.subvendor = PCI_VENDOR_ID_PLX,
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
@@ -2197,6 +2209,11 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_4_921600 },
+ /* Unknown card - subdevice 0x1584 */
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_PLX,
+ PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
+ pbn_b0_4_115200 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_KEYSPAN,
PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8fc7451c004..3b4a14e355c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -942,22 +942,6 @@ config SERIAL_IP22_ZILOG_CONSOLE
depends on SERIAL_IP22_ZILOG=y
select SERIAL_CORE_CONSOLE
-config V850E_UART
- bool "NEC V850E on-chip UART support"
- depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
- select SERIAL_CORE
- default y
-
-config V850E_UARTB
- bool
- depends on V850E_UART && V850E_ME2
- default y
-
-config V850E_UART_CONSOLE
- bool "Use NEC V850E on-chip UART for console"
- depends on V850E_UART
- select SERIAL_CORE_CONSOLE
-
config SERIAL_SH_SCI
tristate "SuperH SCI(F) serial port support"
depends on SUPERH || H8300
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index abe129cc927..a4f86927a74 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -201,6 +201,10 @@ static void cpm_uart_int_tx(struct uart_port *port)
cpm_uart_tx_pump(port);
}
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
/*
* Receive characters
*/
@@ -209,7 +213,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
int i;
unsigned char ch;
u8 *cp;
- struct tty_struct *tty = port->info->tty;
+ struct tty_struct *tty = port->info->port.tty;
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
cbd_t __iomem *bdp;
u16 status;
@@ -222,6 +226,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
*/
bdp = pinfo->rx_cur;
for (;;) {
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return;
+ }
+#endif
/* get status */
status = in_be16(&bdp->cbd_sc);
/* If this one is empty, return happy */
@@ -253,7 +263,12 @@ static void cpm_uart_int_rx(struct uart_port *port)
goto handle_error;
if (uart_handle_sysrq_char(port, ch))
continue;
-
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return;
+ }
+#endif
error_return:
tty_insert_flip_char(tty, ch, flg);
@@ -420,10 +435,13 @@ static void cpm_uart_shutdown(struct uart_port *port)
}
/* Shut them really down and reinit buffer descriptors */
- if (IS_SMC(pinfo))
+ if (IS_SMC(pinfo)) {
+ out_be16(&pinfo->smcup->smc_brkcr, 0);
cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
- else
+ } else {
+ out_be16(&pinfo->sccup->scc_brkcr, 0);
cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
+ }
cpm_uart_initbd(pinfo);
}
@@ -539,9 +557,11 @@ static void cpm_uart_set_termios(struct uart_port *port,
* enables, because we want to put them back if they were
* present.
*/
- prev_mode = in_be16(&smcp->smc_smcmr);
- out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART);
- setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN)));
+ prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
+ /* Output in *one* operation, so we don't interrupt RX/TX if they
+ * were already enabled. */
+ out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
+ SMCMR_SM_UART | prev_mode);
} else {
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
}
@@ -865,6 +885,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
cpm_uart_request_port(port);
}
}
+
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+#define GDB_BUF_SIZE 512 /* power of 2, please */
+
+static char poll_buf[GDB_BUF_SIZE];
+static char *pollp;
+static int poll_chars;
+
+static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
+{
+ u_char c, *cp;
+ volatile cbd_t *bdp;
+ int i;
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = pinfo->rx_cur;
+ while (bdp->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+
+ if (obuf) {
+ i = c = bdp->cbd_datlen;
+ while (i-- > 0)
+ *obuf++ = *cp++;
+ } else
+ c = *cp;
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
+ bdp->cbd_sc |= BD_SC_EMPTY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = pinfo->rx_bd_base;
+ else
+ bdp++;
+ pinfo->rx_cur = (cbd_t *)bdp;
+
+ return (int)c;
+}
+
+static int cpm_get_poll_char(struct uart_port *port)
+{
+ struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+ if (!serial_polled) {
+ serial_polled = 1;
+ poll_chars = 0;
+ }
+ if (poll_chars <= 0) {
+ poll_chars = poll_wait_key(poll_buf, pinfo);
+ pollp = poll_buf;
+ }
+ poll_chars--;
+ return *pollp++;
+}
+
+static void cpm_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+ static char ch[2];
+
+ ch[0] = (char)c;
+ cpm_uart_early_write(pinfo->port.line, ch, 1);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
static struct uart_ops cpm_uart_pops = {
.tx_empty = cpm_uart_tx_empty,
.set_mctrl = cpm_uart_set_mctrl,
@@ -882,6 +976,10 @@ static struct uart_ops cpm_uart_pops = {
.request_port = cpm_uart_request_port,
.config_port = cpm_uart_config_port,
.verify_port = cpm_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = cpm_get_poll_char,
+ .poll_put_char = cpm_put_poll_char,
+#endif
};
struct uart_cpm_port cpm_uart_ports[UART_NR];
@@ -1105,12 +1203,14 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
udbg_putc = NULL;
#endif
- cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
-
if (IS_SMC(pinfo)) {
+ out_be16(&pinfo->smcup->smc_brkcr, 0);
+ cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
} else {
+ out_be16(&pinfo->sccup->scc_brkcr, 0);
+ cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
}
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index a81d2c2ff8a..6042b87797a 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -642,6 +642,26 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
spin_unlock_irqrestore(&dport->port.lock, flags);
}
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void dz_pm(struct uart_port *uport, unsigned int state,
+ unsigned int oldstate)
+{
+ struct dz_port *dport = to_dport(uport);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dport->port.lock, flags);
+ if (state < 3)
+ dz_start_tx(&dport->port);
+ else
+ dz_stop_tx(&dport->port);
+ spin_unlock_irqrestore(&dport->port.lock, flags);
+}
+
+
static const char *dz_type(struct uart_port *uport)
{
return "DZ";
@@ -738,6 +758,7 @@ static struct uart_ops dz_ops = {
.startup = dz_startup,
.shutdown = dz_shutdown,
.set_termios = dz_set_termios,
+ .pm = dz_pm,
.type = dz_type,
.release_port = dz_release_port,
.request_port = dz_request_port,
@@ -861,7 +882,10 @@ static int __init dz_console_setup(struct console *co, char *options)
if (ret)
return ret;
+ spin_lock_init(&dport->port.lock); /* For dz_pm(). */
+
dz_reset(dport);
+ dz_pm(uport, 0, -1);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 9c2df5c857c..2b7531d9f6a 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -730,7 +730,7 @@ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
{
short int count, rcv_buff;
- struct tty_struct *tty = icom_port->uart_port.info->tty;
+ struct tty_struct *tty = icom_port->uart_port.info->port.tty;
unsigned short int status;
struct uart_icount *icount;
unsigned long offset;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index c9f53e71f25..61d3ade5286 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -921,6 +921,10 @@ static int mpsc_make_ready(struct mpsc_port_info *pi)
return 0;
}
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
/*
******************************************************************************
*
@@ -956,7 +960,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
& SDMA_DESC_CMDSTAT_O)) {
bytes_in = be16_to_cpu(rxre->bytecnt);
-
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return 0;
+ }
+#endif
/* Following use of tty struct directly is deprecated */
if (unlikely(tty_buffer_request_room(tty, bytes_in)
< bytes_in)) {
@@ -1017,6 +1026,12 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
if (uart_handle_sysrq_char(&pi->port, *bp)) {
bp++;
bytes_in--;
+#ifdef CONFIG_CONSOLE_POLL
+ if (unlikely(serial_polled)) {
+ serial_polled = 0;
+ return 0;
+ }
+#endif
goto next_frame;
}
@@ -1519,6 +1534,133 @@ static int mpsc_verify_port(struct uart_port *port, struct serial_struct *ser)
return rc;
}
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static char poll_buf[2048];
+static int poll_ptr;
+static int poll_cnt;
+static void mpsc_put_poll_char(struct uart_port *port,
+ unsigned char c);
+
+static int mpsc_get_poll_char(struct uart_port *port)
+{
+ struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+ struct mpsc_rx_desc *rxre;
+ u32 cmdstat, bytes_in, i;
+ u8 *bp;
+
+ if (!serial_polled)
+ serial_polled = 1;
+
+ pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
+
+ if (poll_cnt) {
+ poll_cnt--;
+ return poll_buf[poll_ptr++];
+ }
+ poll_ptr = 0;
+ poll_cnt = 0;
+
+ while (poll_cnt == 0) {
+ rxre = (struct mpsc_rx_desc *)(pi->rxr +
+ (pi->rxr_posn*MPSC_RXRE_SIZE));
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+ /*
+ * Loop through Rx descriptors handling ones that have
+ * been completed.
+ */
+ while (poll_cnt == 0 &&
+ !((cmdstat = be32_to_cpu(rxre->cmdstat)) &
+ SDMA_DESC_CMDSTAT_O)){
+ bytes_in = be16_to_cpu(rxre->bytecnt);
+ bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
+ dma_cache_sync(pi->port.dev, (void *) bp,
+ MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)bp,
+ (ulong)bp + MPSC_RXBE_SIZE);
+#endif
+ if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
+ SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
+ !(cmdstat & pi->port.ignore_status_mask)) {
+ poll_buf[poll_cnt] = *bp;
+ poll_cnt++;
+ } else {
+ for (i = 0; i < bytes_in; i++) {
+ poll_buf[poll_cnt] = *bp++;
+ poll_cnt++;
+ }
+ pi->port.icount.rx += bytes_in;
+ }
+ rxre->bytecnt = cpu_to_be16(0);
+ wmb();
+ rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
+ SDMA_DESC_CMDSTAT_EI |
+ SDMA_DESC_CMDSTAT_F |
+ SDMA_DESC_CMDSTAT_L);
+ wmb();
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ flush_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+
+ /* Advance to next descriptor */
+ pi->rxr_posn = (pi->rxr_posn + 1) &
+ (MPSC_RXR_ENTRIES - 1);
+ rxre = (struct mpsc_rx_desc *)(pi->rxr +
+ (pi->rxr_posn * MPSC_RXRE_SIZE));
+ dma_cache_sync(pi->port.dev, (void *)rxre,
+ MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+ if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+ invalidate_dcache_range((ulong)rxre,
+ (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+ }
+
+ /* Restart rx engine, if its stopped */
+ if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
+ mpsc_start_rx(pi);
+ }
+ if (poll_cnt) {
+ poll_cnt--;
+ return poll_buf[poll_ptr++];
+ }
+
+ return 0;
+}
+
+
+static void mpsc_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+ u32 data;
+
+ data = readl(pi->mpsc_base + MPSC_MPCR);
+ writeb(c, pi->mpsc_base + MPSC_CHR_1);
+ mb();
+ data = readl(pi->mpsc_base + MPSC_CHR_2);
+ data |= MPSC_CHR_2_TTCS;
+ writel(data, pi->mpsc_base + MPSC_CHR_2);
+ mb();
+
+ while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
+}
+#endif
static struct uart_ops mpsc_pops = {
.tx_empty = mpsc_tx_empty,
@@ -1537,6 +1679,10 @@ static struct uart_ops mpsc_pops = {
.request_port = mpsc_request_port,
.config_port = mpsc_config_port,
.verify_port = mpsc_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = mpsc_get_poll_char,
+ .poll_put_char = mpsc_put_poll_char,
+#endif
};
/*
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 4a3ecaa629e..d852f83f890 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -202,7 +202,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
- struct tty_struct *tty = port->info->tty;
+ struct tty_struct *tty = port->info->port.tty;
unsigned int ufcon, ch, flag, ufstat, uerstat;
int max_count = 64;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0bce1fe2c62..f977c98cfa9 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
return ret;
}
-static void uart_break_ctl(struct tty_struct *tty, int break_state)
+static int uart_break_ctl(struct tty_struct *tty, int break_state)
{
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->port;
@@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
port->ops->break_ctl(port, break_state);
mutex_unlock(&state->mutex);
+ return 0;
}
static int uart_do_autoconfig(struct uart_state *state)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 7ad21925869..8fcb4c5b9a2 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -272,7 +272,7 @@ static void serial_txx9_initialize(struct uart_port *port)
static inline void
receive_chars(struct uart_txx9_port *up, unsigned int *status)
{
- struct tty_struct *tty = up->port.info->tty;
+ struct tty_struct *tty = up->port.info->port.tty;
unsigned char ch;
unsigned int disr = *status;
int max_count = 256;
diff --git a/drivers/serial/zs.c b/drivers/serial/zs.c
index bd45b6230fd..9e6a873f820 100644
--- a/drivers/serial/zs.c
+++ b/drivers/serial/zs.c
@@ -787,7 +787,6 @@ static int zs_startup(struct uart_port *uport)
zport->regs[1] &= ~RxINT_MASK;
zport->regs[1] |= RxINT_ALL | TxINT_ENAB | EXT_INT_ENAB;
zport->regs[3] |= RxENABLE;
- zport->regs[5] |= TxENAB;
zport->regs[15] |= BRKIE;
write_zsreg(zport, R1, zport->regs[1]);
write_zsreg(zport, R3, zport->regs[3]);
@@ -814,7 +813,6 @@ static void zs_shutdown(struct uart_port *uport)
spin_lock_irqsave(&scc->zlock, flags);
- zport->regs[5] &= ~TxENAB;
zport->regs[3] &= ~RxENABLE;
write_zsreg(zport, R5, zport->regs[5]);
write_zsreg(zport, R3, zport->regs[3]);
@@ -959,6 +957,23 @@ static void zs_set_termios(struct uart_port *uport, struct ktermios *termios,
spin_unlock_irqrestore(&scc->zlock, flags);
}
+/*
+ * Hack alert!
+ * Required solely so that the initial PROM-based console
+ * works undisturbed in parallel with this one.
+ */
+static void zs_pm(struct uart_port *uport, unsigned int state,
+ unsigned int oldstate)
+{
+ struct zs_port *zport = to_zport(uport);
+
+ if (state < 3)
+ zport->regs[5] |= TxENAB;
+ else
+ zport->regs[5] &= ~TxENAB;
+ write_zsreg(zport, R5, zport->regs[5]);
+}
+
static const char *zs_type(struct uart_port *uport)
{
@@ -1041,6 +1056,7 @@ static struct uart_ops zs_ops = {
.startup = zs_startup,
.shutdown = zs_shutdown,
.set_termios = zs_set_termios,
+ .pm = zs_pm,
.type = zs_type,
.release_port = zs_release_port,
.request_port = zs_request_port,
@@ -1190,6 +1206,7 @@ static int __init zs_console_setup(struct console *co, char *options)
return ret;
zs_reset(zport);
+ zs_pm(uport, 0, -1);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 66ec5d8808d..2303521b4f0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -49,25 +49,26 @@ config SPI_MASTER
controller and the protocol drivers for the SPI slave chips
that are connected.
+if SPI_MASTER
+
comment "SPI Master Controller Drivers"
- depends on SPI_MASTER
config SPI_ATMEL
tristate "Atmel SPI Controller"
- depends on (ARCH_AT91 || AVR32) && SPI_MASTER
+ depends on (ARCH_AT91 || AVR32)
help
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
config SPI_BFIN
tristate "SPI controller driver for ADI Blackfin5xx"
- depends on SPI_MASTER && BLACKFIN
+ depends on BLACKFIN
help
This is the SPI controller master driver for Blackfin 5xx processor.
config SPI_AU1550
tristate "Au1550/Au12x0 SPI Controller"
- depends on SPI_MASTER && (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
+ depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
select SPI_BITBANG
help
If you say yes to this option, support will be included for the
@@ -78,7 +79,6 @@ config SPI_AU1550
config SPI_BITBANG
tristate "Bitbanging SPI master"
- depends on SPI_MASTER && EXPERIMENTAL
help
With a few GPIO pins, your system can bitbang the SPI protocol.
Select this to get SPI support through I/O pins (GPIO, parallel
@@ -92,7 +92,7 @@ config SPI_BITBANG
config SPI_BUTTERFLY
tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ depends on PARPORT
select SPI_BITBANG
help
This uses a custom parallel port cable to connect to an AVR
@@ -102,14 +102,14 @@ config SPI_BUTTERFLY
config SPI_IMX
tristate "Freescale iMX SPI controller"
- depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+ depends on ARCH_IMX && EXPERIMENTAL
help
This enables using the Freescale iMX SPI controller in master
mode.
config SPI_LM70_LLP
tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
- depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ depends on PARPORT && EXPERIMENTAL
select SPI_BITBANG
help
This driver supports the NS LM70 LLP Evaluation Board,
@@ -118,14 +118,14 @@ config SPI_LM70_LLP
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
- depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+ depends on PPC_MPC52xx && EXPERIMENTAL
help
This enables using the Freescale MPC52xx Programmable Serial
Controller in master SPI mode.
config SPI_MPC83xx
tristate "Freescale MPC83xx/QUICC Engine SPI controller"
- depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
+ depends on (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL
help
This enables using the Freescale MPC83xx and QUICC Engine SPI
controllers in master mode.
@@ -137,21 +137,21 @@ config SPI_MPC83xx
config SPI_OMAP_UWIRE
tristate "OMAP1 MicroWire"
- depends on SPI_MASTER && ARCH_OMAP1
+ depends on ARCH_OMAP1
select SPI_BITBANG
help
This hooks up to the MicroWire controller on OMAP1 chips.
config SPI_OMAP24XX
tristate "McSPI driver for OMAP24xx/OMAP34xx"
- depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX)
+ depends on ARCH_OMAP24XX || ARCH_OMAP34XX
help
SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
(McSPI) modules.
config SPI_PXA2XX
tristate "PXA2xx SSP SPI master"
- depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
+ depends on ARCH_PXA && EXPERIMENTAL
select PXA_SSP
help
This enables using a PXA2xx SSP port as a SPI master controller.
@@ -160,14 +160,14 @@ config SPI_PXA2XX
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
- depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ depends on ARCH_S3C2410 && EXPERIMENTAL
select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs
config SPI_S3C24XX_GPIO
tristate "Samsung S3C24XX series SPI by GPIO"
- depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+ depends on ARCH_S3C2410 && EXPERIMENTAL
select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs using
@@ -177,20 +177,20 @@ config SPI_S3C24XX_GPIO
config SPI_SH_SCI
tristate "SuperH SCI SPI controller"
- depends on SPI_MASTER && SUPERH
+ depends on SUPERH
select SPI_BITBANG
help
SPI driver for SuperH SCI blocks.
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
- depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
+ depends on GENERIC_GPIO && CPU_TX49XX
help
SPI driver for Toshiba TXx9 MIPS SoCs
config SPI_XILINX
tristate "Xilinx SPI controller"
- depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
+ depends on XILINX_VIRTEX && EXPERIMENTAL
select SPI_BITBANG
help
This exposes the SPI controller IP from the Xilinx EDK.
@@ -207,11 +207,10 @@ config SPI_XILINX
# being probably the most widely used ones.
#
comment "SPI Protocol Masters"
- depends on SPI_MASTER
config SPI_AT25
tristate "SPI EEPROMs from most vendors"
- depends on SPI_MASTER && SYSFS
+ depends on SYSFS
help
Enable this driver to get read/write support to most SPI EEPROMs,
after you configure the board init code to know about each eeprom
@@ -222,7 +221,7 @@ config SPI_AT25
config SPI_SPIDEV
tristate "User mode SPI device driver support"
- depends on SPI_MASTER && EXPERIMENTAL
+ depends on EXPERIMENTAL
help
This supports user mode SPI protocol drivers.
@@ -231,7 +230,7 @@ config SPI_SPIDEV
config SPI_TLE62X0
tristate "Infineon TLE62X0 (for power switching)"
- depends on SPI_MASTER && SYSFS
+ depends on SYSFS
help
SPI driver for Infineon TLE62X0 series line driver chips,
such as the TLE6220, TLE6230 and TLE6240. This provides a
@@ -242,6 +241,8 @@ config SPI_TLE62X0
# Add new SPI protocol masters in alphabetical order above this line
#
+endif # SPI_MASTER
+
# (slave support would go here)
endif # SPI
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index 072c4a59533..9149689c79d 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -26,6 +26,7 @@
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/resource.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/dma-mapping.h>
@@ -81,6 +82,7 @@ struct au1550_spi {
struct spi_master *master;
struct device *dev;
struct au1550_spi_info *pdata;
+ struct resource *ioarea;
};
@@ -96,6 +98,8 @@ static dbdev_tab_t au1550_spi_mem_dbdev =
.dev_intpolarity = 0
};
+static int ddma_memid; /* id to above mem dma device */
+
static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw);
@@ -480,9 +484,13 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
au1xxx_dbdma_reset(hw->dma_tx_ch);
au1550_spi_reset_fifos(hw);
- dev_err(hw->dev,
- "Unexpected SPI error: event=0x%x stat=0x%x!\n",
- evnt, stat);
+ if (evnt == PSC_SPIEVNT_RO)
+ dev_err(hw->dev,
+ "dma transfer: receive FIFO overflow!\n");
+ else
+ dev_err(hw->dev,
+ "dma transfer: unexpected SPI error "
+ "(event=0x%x stat=0x%x)!\n", evnt, stat);
complete(&hw->master_done);
return IRQ_HANDLED;
@@ -592,17 +600,17 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
if ((evnt & (PSC_SPIEVNT_MM | PSC_SPIEVNT_RO
| PSC_SPIEVNT_RU | PSC_SPIEVNT_TO
- | PSC_SPIEVNT_TU | PSC_SPIEVNT_SD))
+ | PSC_SPIEVNT_SD))
!= 0) {
- dev_err(hw->dev,
- "Unexpected SPI error: event=0x%x stat=0x%x!\n",
- evnt, stat);
/*
* due to an error we consider transfer as done,
* so mask all events until before next transfer start
*/
au1550_spi_mask_ack_all(hw);
au1550_spi_reset_fifos(hw);
+ dev_err(hw->dev,
+ "pio transfer: unexpected SPI error "
+ "(event=0x%x stat=0x%x)!\n", evnt, stat);
complete(&hw->master_done);
return IRQ_HANDLED;
}
@@ -616,27 +624,50 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
stat = hw->regs->psc_spistat;
au_sync();
- if ((stat & PSC_SPISTAT_RE) == 0 && hw->rx_count < hw->len) {
+ /*
+ * Take care to not let the Rx FIFO overflow.
+ *
+ * We only write a byte if we have read one at least. Initially,
+ * the write fifo is full, so we should read from the read fifo
+ * first.
+ * In case we miss a word from the read fifo, we should get a
+ * RO event and should back out.
+ */
+ if (!(stat & PSC_SPISTAT_RE) && hw->rx_count < hw->len) {
hw->rx_word(hw);
- /* ack the receive request event */
- hw->regs->psc_spievent = PSC_SPIEVNT_RR;
- au_sync();
busy = 1;
- }
- if ((stat & PSC_SPISTAT_TF) == 0 && hw->tx_count < hw->len) {
- hw->tx_word(hw);
- /* ack the transmit request event */
- hw->regs->psc_spievent = PSC_SPIEVNT_TR;
- au_sync();
- busy = 1;
+ if (!(stat & PSC_SPISTAT_TF) && hw->tx_count < hw->len)
+ hw->tx_word(hw);
}
} while (busy);
- evnt = hw->regs->psc_spievent;
+ hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
au_sync();
- if (hw->rx_count >= hw->len || (evnt & PSC_SPIEVNT_MD) != 0) {
+ /*
+ * Restart the SPI transmission in case of a transmit underflow.
+ * This seems to work despite the notes in the Au1550 data book
+ * of Figure 8-4 with flowchart for SPI master operation:
+ *
+ * """Note 1: An XFR Error Interrupt occurs, unless masked,
+ * for any of the following events: Tx FIFO Underflow,
+ * Rx FIFO Overflow, or Multiple-master Error
+ * Note 2: In case of a Tx Underflow Error, all zeroes are
+ * transmitted."""
+ *
+ * By simply restarting the spi transfer on Tx Underflow Error,
+ * we assume that spi transfer was paused instead of zeroes
+ * transmittion mentioned in the Note 2 of Au1550 data book.
+ */
+ if (evnt & PSC_SPIEVNT_TU) {
+ hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
+ au_sync();
+ hw->regs->psc_spipcr = PSC_SPIPCR_MS;
+ au_sync();
+ }
+
+ if (hw->rx_count >= hw->len) {
/* transfer completed successfully */
au1550_spi_mask_ack_all(hw);
complete(&hw->master_done);
@@ -725,6 +756,8 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
stat = hw->regs->psc_spistat;
au_sync();
} while ((stat & PSC_SPISTAT_DR) == 0);
+
+ au1550_spi_reset_fifos(hw);
}
@@ -732,6 +765,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
{
struct au1550_spi *hw;
struct spi_master *master;
+ struct resource *r;
int err = 0;
master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi));
@@ -753,76 +787,64 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
goto err_no_pdata;
}
- platform_set_drvdata(pdev, hw);
-
- init_completion(&hw->master_done);
-
- hw->bitbang.master = hw->master;
- hw->bitbang.setup_transfer = au1550_spi_setupxfer;
- hw->bitbang.chipselect = au1550_spi_chipsel;
- hw->bitbang.master->setup = au1550_spi_setup;
- hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no IRQ\n");
+ err = -ENODEV;
+ goto err_no_iores;
+ }
+ hw->irq = r->start;
+
+ hw->usedma = 0;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (r) {
+ hw->dma_tx_id = r->start;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (r) {
+ hw->dma_rx_id = r->start;
+ if (usedma && ddma_memid) {
+ if (pdev->dev.dma_mask == NULL)
+ dev_warn(&pdev->dev, "no dma mask\n");
+ else
+ hw->usedma = 1;
+ }
+ }
+ }
- switch (hw->pdata->bus_num) {
- case 0:
- hw->irq = AU1550_PSC0_INT;
- hw->regs = (volatile psc_spi_t *)PSC0_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC0_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC0_TX;
- break;
- case 1:
- hw->irq = AU1550_PSC1_INT;
- hw->regs = (volatile psc_spi_t *)PSC1_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC1_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC1_TX;
- break;
- case 2:
- hw->irq = AU1550_PSC2_INT;
- hw->regs = (volatile psc_spi_t *)PSC2_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC2_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC2_TX;
- break;
- case 3:
- hw->irq = AU1550_PSC3_INT;
- hw->regs = (volatile psc_spi_t *)PSC3_BASE_ADDR;
- hw->dma_rx_id = DSCR_CMD0_PSC3_RX;
- hw->dma_tx_id = DSCR_CMD0_PSC3_TX;
- break;
- default:
- dev_err(&pdev->dev, "Wrong bus_num of SPI\n");
- err = -ENOENT;
- goto err_no_pdata;
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no mmio resource\n");
+ err = -ENODEV;
+ goto err_no_iores;
}
- if (request_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t),
- pdev->name) == NULL) {
+ hw->ioarea = request_mem_region(r->start, sizeof(psc_spi_t),
+ pdev->name);
+ if (!hw->ioarea) {
dev_err(&pdev->dev, "Cannot reserve iomem region\n");
err = -ENXIO;
goto err_no_iores;
}
-
- if (usedma) {
- if (pdev->dev.dma_mask == NULL)
- dev_warn(&pdev->dev, "no dma mask\n");
- else
- hw->usedma = 1;
+ hw->regs = (psc_spi_t __iomem *)ioremap(r->start, sizeof(psc_spi_t));
+ if (!hw->regs) {
+ dev_err(&pdev->dev, "cannot ioremap\n");
+ err = -ENXIO;
+ goto err_ioremap;
}
- if (hw->usedma) {
- /*
- * create memory device with 8 bits dev_devwidth
- * needed for proper byte ordering to spi fifo
- */
- int memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
- if (!memid) {
- dev_err(&pdev->dev,
- "Cannot create dma 8 bit mem device\n");
- err = -ENXIO;
- goto err_dma_add_dev;
- }
+ platform_set_drvdata(pdev, hw);
+
+ init_completion(&hw->master_done);
+
+ hw->bitbang.master = hw->master;
+ hw->bitbang.setup_transfer = au1550_spi_setupxfer;
+ hw->bitbang.chipselect = au1550_spi_chipsel;
+ hw->bitbang.master->setup = au1550_spi_setup;
+ hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs;
- hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(memid,
+ if (hw->usedma) {
+ hw->dma_tx_ch = au1xxx_dbdma_chan_alloc(ddma_memid,
hw->dma_tx_id, NULL, (void *)hw);
if (hw->dma_tx_ch == 0) {
dev_err(&pdev->dev,
@@ -841,7 +863,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
hw->dma_rx_ch = au1xxx_dbdma_chan_alloc(hw->dma_rx_id,
- memid, NULL, (void *)hw);
+ ddma_memid, NULL, (void *)hw);
if (hw->dma_rx_ch == 0) {
dev_err(&pdev->dev,
"Cannot allocate rx dma channel\n");
@@ -874,7 +896,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
goto err_no_irq;
}
- master->bus_num = hw->pdata->bus_num;
+ master->bus_num = pdev->id;
master->num_chipselect = hw->pdata->num_chipselect;
/*
@@ -924,8 +946,11 @@ err_no_txdma_descr:
au1xxx_dbdma_chan_free(hw->dma_tx_ch);
err_no_txdma:
-err_dma_add_dev:
- release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+ iounmap((void __iomem *)hw->regs);
+
+err_ioremap:
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
err_no_iores:
err_no_pdata:
@@ -944,7 +969,9 @@ static int __exit au1550_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&hw->bitbang);
free_irq(hw->irq, hw);
- release_mem_region((unsigned long)hw->regs, sizeof(psc_spi_t));
+ iounmap((void __iomem *)hw->regs);
+ release_resource(hw->ioarea);
+ kfree(hw->ioarea);
if (hw->usedma) {
au1550_spi_dma_rxtmp_free(hw);
@@ -971,12 +998,24 @@ static struct platform_driver au1550_spi_drv = {
static int __init au1550_spi_init(void)
{
+ /*
+ * create memory device with 8 bits dev_devwidth
+ * needed for proper byte ordering to spi fifo
+ */
+ if (usedma) {
+ ddma_memid = au1xxx_ddma_add_device(&au1550_spi_mem_dbdev);
+ if (!ddma_memid)
+ printk(KERN_ERR "au1550-spi: cannot add memory"
+ "dbdma device\n");
+ }
return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
}
module_init(au1550_spi_init);
static void __exit au1550_spi_exit(void)
{
+ if (usedma && ddma_memid)
+ au1xxx_ddma_del_device(ddma_memid);
platform_driver_unregister(&au1550_spi_drv);
}
module_exit(au1550_spi_exit);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1ad12afc6ba..ecca4a6a6f9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -218,6 +218,8 @@ struct spi_device *spi_new_device(struct spi_master *master,
if (!spi_master_get(master))
return NULL;
+ WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
+
proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
if (!proxy) {
dev_err(dev, "can't alloc dev for cs%d\n",
@@ -229,7 +231,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
- proxy->modalias = chip->modalias;
+ strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
"%s.%u", master->dev.bus_id,
@@ -502,7 +504,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num)
struct device *dev;
struct spi_master *master = NULL;
- dev = class_find_device(&spi_master_class, &bus_num,
+ dev = class_find_device(&spi_master_class, NULL, &bus_num,
__spi_master_match);
if (dev)
master = container_of(dev, struct spi_master, dev);
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
index 6832da6f710..070c6219e2d 100644
--- a/drivers/spi/spi_mpc83xx.c
+++ b/drivers/spi/spi_mpc83xx.c
@@ -266,21 +266,24 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
cs->hw_mode |= SPMODE_LEN(bits_per_word);
- if ((mpc83xx_spi->spibrg / hz) >= 64) {
- pm = mpc83xx_spi->spibrg / (hz * 64) - 1;
- if (pm > 0x0f) {
- dev_err(&spi->dev, "Requested speed is too "
- "low: %d Hz. Will use %d Hz instead.\n",
- hz, mpc83xx_spi->spibrg / 1024);
- pm = 0x0f;
+ if ((mpc83xx_spi->spibrg / hz) > 64) {
+ pm = mpc83xx_spi->spibrg / (hz * 64);
+ if (pm > 16) {
+ cs->hw_mode |= SPMODE_DIV16;
+ pm /= 16;
+ if (pm > 16) {
+ dev_err(&spi->dev, "Requested speed is too "
+ "low: %d Hz. Will use %d Hz instead.\n",
+ hz, mpc83xx_spi->spibrg / 1024);
+ pm = 16;
+ }
}
- cs->hw_mode |= SPMODE_PM(pm) | SPMODE_DIV16;
- } else {
+ } else
pm = mpc83xx_spi->spibrg / (hz * 4);
- if (pm)
- pm--;
- cs->hw_mode |= SPMODE_PM(pm);
- }
+ if (pm)
+ pm--;
+
+ cs->hw_mode |= SPMODE_PM(pm);
regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
if (cs->hw_mode != regval) {
unsigned long flags;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ddbe1a5e970..e5e0cfed5e3 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -228,7 +228,6 @@ static int spidev_message(struct spidev_data *spidev,
* We walk the array of user-provided transfers, using each one
* to initialize a kernel version of the same transfer.
*/
- mutex_lock(&spidev->buf_lock);
buf = spidev->buffer;
total = 0;
for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
@@ -296,14 +295,12 @@ static int spidev_message(struct spidev_data *spidev,
status = total;
done:
- mutex_unlock(&spidev->buf_lock);
kfree(k_xfers);
return status;
}
-static int
-spidev_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long
+spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
int retval = 0;
@@ -341,6 +338,14 @@ spidev_ioctl(struct inode *inode, struct file *filp,
if (spi == NULL)
return -ESHUTDOWN;
+ /* use the buffer lock here for triple duty:
+ * - prevent I/O (from us) so calling spi_setup() is safe;
+ * - prevent concurrent SPI_IOC_WR_* from morphing
+ * data fields while SPI_IOC_RD_* reads them;
+ * - SPI_IOC_MESSAGE needs the buffer locked "normally".
+ */
+ mutex_lock(&spidev->buf_lock);
+
switch (cmd) {
/* read requests */
case SPI_IOC_RD_MODE:
@@ -456,6 +461,8 @@ spidev_ioctl(struct inode *inode, struct file *filp,
kfree(ioc);
break;
}
+
+ mutex_unlock(&spidev->buf_lock);
spi_dev_put(spi);
return retval;
}
@@ -533,7 +540,7 @@ static struct file_operations spidev_fops = {
*/
.write = spidev_write,
.read = spidev_read,
- .ioctl = spidev_ioctl,
+ .unlocked_ioctl = spidev_ioctl,
.open = spidev_open,
.release = spidev_release,
};
@@ -576,7 +583,8 @@ static int spidev_probe(struct spi_device *spi)
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create(spidev_class, &spi->dev, spidev->devt,
+ dev = device_create_drvdata(spidev_class, &spi->dev,
+ spidev->devt, spidev,
"spidev%d.%d",
spi->master->bus_num, spi->chip_select);
status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
@@ -586,7 +594,6 @@ static int spidev_probe(struct spi_device *spi)
}
if (status == 0) {
set_bit(minor, minors);
- spi_set_drvdata(spi, spidev);
list_add(&spidev->device_entry, &device_list);
}
mutex_unlock(&device_list_lock);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 113a0468ffc..68d6f4988fb 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -353,11 +353,12 @@ static int __init xilinx_spi_probe(struct platform_device *dev)
goto put_master;
}
- xspi->irq = platform_get_irq(dev, 0);
- if (xspi->irq < 0) {
+ ret = platform_get_irq(dev, 0);
+ if (ret < 0) {
ret = -ENXIO;
goto unmap_io;
}
+ xspi->irq = ret;
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index a4aaab9c7dd..2e9079df26b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -15,7 +15,7 @@ if UIO
config UIO_CIF
tristate "generic Hilscher CIF Card driver"
- depends on UIO && PCI
+ depends on PCI
default n
help
Driver for Hilscher CIF DeviceNet and Profibus cards. This
@@ -26,9 +26,15 @@ config UIO_CIF
To compile this driver as a module, choose M here: the module
will be called uio_cif.
+config UIO_PDRV
+ tristate "Userspace I/O platform driver"
+ help
+ Generic platform driver for Userspace I/O devices.
+
+ If you don't know what to do here, say N.
+
config UIO_SMX
tristate "SMX cryptengine UIO interface"
- depends on UIO
default n
help
Userspace IO interface to the Cryptography engine found on the
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18c45662431..e00ce0def1a 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o
+obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_SMX) += uio_smx.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 5a7ca2e6094..3a6934bf713 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -427,6 +427,31 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
return retval;
}
+static ssize_t uio_write(struct file *filep, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct uio_listener *listener = filep->private_data;
+ struct uio_device *idev = listener->dev;
+ ssize_t retval;
+ s32 irq_on;
+
+ if (idev->info->irq == UIO_IRQ_NONE)
+ return -EIO;
+
+ if (count != sizeof(s32))
+ return -EINVAL;
+
+ if (!idev->info->irqcontrol)
+ return -ENOSYS;
+
+ if (copy_from_user(&irq_on, buf, count))
+ return -EFAULT;
+
+ retval = idev->info->irqcontrol(idev->info, irq_on);
+
+ return retval ? retval : sizeof(s32);
+}
+
static int uio_find_mem_index(struct vm_area_struct *vma)
{
int mi;
@@ -546,6 +571,7 @@ static const struct file_operations uio_fops = {
.open = uio_open,
.release = uio_release,
.read = uio_read,
+ .write = uio_write,
.mmap = uio_mmap,
.poll = uio_poll,
.fasync = uio_fasync,
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
new file mode 100644
index 00000000000..5d0d2e85d98
--- /dev/null
+++ b/drivers/uio/uio_pdrv.c
@@ -0,0 +1,118 @@
+/*
+ * drivers/uio/uio_pdrv.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/stringify.h>
+
+#define DRIVER_NAME "uio"
+
+struct uio_platdata {
+ struct uio_info *uioinfo;
+};
+
+static int uio_pdrv_probe(struct platform_device *pdev)
+{
+ struct uio_info *uioinfo = pdev->dev.platform_data;
+ struct uio_platdata *pdata;
+ struct uio_mem *uiomem;
+ int ret = -ENODEV;
+ int i;
+
+ if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+ dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
+ goto err_uioinfo;
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ ret = -ENOMEM;
+ dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
+ goto err_alloc_pdata;
+ }
+
+ pdata->uioinfo = uioinfo;
+
+ uiomem = &uioinfo->mem[0];
+
+ for (i = 0; i < pdev->num_resources; ++i) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags != IORESOURCE_MEM)
+ continue;
+
+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+ dev_warn(&pdev->dev, "device has more than "
+ __stringify(MAX_UIO_MAPS)
+ " I/O memory resources.\n");
+ break;
+ }
+
+ uiomem->memtype = UIO_MEM_PHYS;
+ uiomem->addr = r->start;
+ uiomem->size = r->end - r->start + 1;
+ ++uiomem;
+ }
+
+ while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+ uiomem->size = 0;
+ ++uiomem;
+ }
+
+ pdata->uioinfo->priv = pdata;
+
+ ret = uio_register_device(&pdev->dev, pdata->uioinfo);
+
+ if (ret) {
+ kfree(pdata);
+err_alloc_pdata:
+err_uioinfo:
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pdata);
+
+ return 0;
+}
+
+static int uio_pdrv_remove(struct platform_device *pdev)
+{
+ struct uio_platdata *pdata = platform_get_drvdata(pdev);
+
+ uio_unregister_device(pdata->uioinfo);
+
+ return 0;
+}
+
+static struct platform_driver uio_pdrv = {
+ .probe = uio_pdrv_probe,
+ .remove = uio_pdrv_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init uio_pdrv_init(void)
+{
+ return platform_driver_register(&uio_pdrv);
+}
+
+static void __exit uio_pdrv_exit(void)
+{
+ platform_driver_unregister(&uio_pdrv);
+}
+module_init(uio_pdrv_init);
+module_exit(uio_pdrv_exit);
+
+MODULE_AUTHOR("Uwe Kleine-Koenig");
+MODULE_DESCRIPTION("Userspace I/O platform driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 90583d6a594..507a9bd0d77 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -1052,7 +1052,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
instance->usbatm = usbatm_instance;
instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
- memset(instance->card_info, 0, sizeof(instance->card_info));
mutex_init(&instance->poll_state_serialize);
instance->poll_state = CXPOLL_STOPPED;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7d27c9cf3c4..76fce44c2f9 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -829,7 +829,6 @@ static int speedtch_bind(struct usbatm_data *usbatm,
if (use_isoc) {
const struct usb_host_interface *desc = data_intf->cur_altsetting;
const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in;
- int i;
use_isoc = 0; /* fall back to bulk if endpoint not found */
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index c3201affa0b..0725b1871f2 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -159,12 +159,34 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb)
spin_lock_irqsave(&acm->write_lock, flags);
acm->write_ready = 1;
wb->use = 0;
+ acm->transmitting--;
spin_unlock_irqrestore(&acm->write_lock, flags);
}
/*
* Poke write.
+ *
+ * the caller is responsible for locking
*/
+
+static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
+{
+ int rc;
+
+ acm->transmitting++;
+
+ wb->urb->transfer_buffer = wb->buf;
+ wb->urb->transfer_dma = wb->dmah;
+ wb->urb->transfer_buffer_length = wb->len;
+ wb->urb->dev = acm->dev;
+
+ if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
+ dbg("usb_submit_urb(write bulk) failed: %d", rc);
+ acm_write_done(acm, wb);
+ }
+ return rc;
+}
+
static int acm_write_start(struct acm *acm, int wbn)
{
unsigned long flags;
@@ -182,26 +204,31 @@ static int acm_write_start(struct acm *acm, int wbn)
return 0; /* A white lie */
}
+ wb = &acm->wb[wbn];
+ if(acm_wb_is_avail(acm) <= 1)
+ acm->write_ready = 0;
+
+ dbg("%s susp_count: %d", __func__, acm->susp_count);
+ if (acm->susp_count) {
+ acm->old_ready = acm->write_ready;
+ acm->delayed_wb = wb;
+ acm->write_ready = 0;
+ schedule_work(&acm->waker);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return 0; /* A white lie */
+ }
+ usb_mark_last_busy(acm->dev);
+
if (!acm_wb_is_used(acm, wbn)) {
spin_unlock_irqrestore(&acm->write_lock, flags);
return 0;
}
- wb = &acm->wb[wbn];
- if(acm_wb_is_avail(acm) <= 1)
- acm->write_ready = 0;
+ rc = acm_start_wb(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags);
- wb->urb->transfer_buffer = wb->buf;
- wb->urb->transfer_dma = wb->dmah;
- wb->urb->transfer_buffer_length = wb->len;
- wb->urb->dev = acm->dev;
-
- if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
- dbg("usb_submit_urb(write bulk) failed: %d", rc);
- acm_write_done(acm, wb);
- }
return rc;
+
}
/*
* attributes exported through sysfs
@@ -304,6 +331,7 @@ static void acm_ctrl_irq(struct urb *urb)
break;
}
exit:
+ usb_mark_last_busy(acm->dev);
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
@@ -320,8 +348,11 @@ static void acm_read_bulk(struct urb *urb)
dbg("Entering acm_read_bulk with status %d", status);
- if (!ACM_READY(acm))
+ if (!ACM_READY(acm)) {
+ dev_dbg(&acm->data->dev, "Aborting, acm not ready");
return;
+ }
+ usb_mark_last_busy(acm->dev);
if (status)
dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
@@ -331,6 +362,7 @@ static void acm_read_bulk(struct urb *urb)
if (likely(status == 0)) {
spin_lock(&acm->read_lock);
+ acm->processing++;
list_add_tail(&rcv->list, &acm->spare_read_urbs);
list_add_tail(&buf->list, &acm->filled_read_bufs);
spin_unlock(&acm->read_lock);
@@ -343,7 +375,8 @@ static void acm_read_bulk(struct urb *urb)
/* nevertheless the tasklet must be kicked unconditionally
so the queue cannot dry up */
}
- tasklet_schedule(&acm->urb_task);
+ if (likely(!acm->susp_count))
+ tasklet_schedule(&acm->urb_task);
}
static void acm_rx_tasklet(unsigned long _acm)
@@ -354,16 +387,23 @@ static void acm_rx_tasklet(unsigned long _acm)
struct acm_ru *rcv;
unsigned long flags;
unsigned char throttled;
+
dbg("Entering acm_rx_tasklet");
if (!ACM_READY(acm))
+ {
+ dbg("acm_rx_tasklet: ACM not ready");
return;
+ }
spin_lock_irqsave(&acm->throttle_lock, flags);
throttled = acm->throttle;
spin_unlock_irqrestore(&acm->throttle_lock, flags);
if (throttled)
+ {
+ dbg("acm_rx_tasklet: throttled");
return;
+ }
next_buffer:
spin_lock_irqsave(&acm->read_lock, flags);
@@ -403,6 +443,7 @@ urbs:
while (!list_empty(&acm->spare_read_bufs)) {
spin_lock_irqsave(&acm->read_lock, flags);
if (list_empty(&acm->spare_read_urbs)) {
+ acm->processing = 0;
spin_unlock_irqrestore(&acm->read_lock, flags);
return;
}
@@ -425,18 +466,23 @@ urbs:
rcv->urb->transfer_dma = buf->dma;
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
-
/* This shouldn't kill the driver as unsuccessful URBs are returned to the
free-urbs-pool and resubmited ASAP */
- if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+ spin_lock_irqsave(&acm->read_lock, flags);
+ if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
list_add(&buf->list, &acm->spare_read_bufs);
- spin_lock_irqsave(&acm->read_lock, flags);
list_add(&rcv->list, &acm->spare_read_urbs);
+ acm->processing = 0;
spin_unlock_irqrestore(&acm->read_lock, flags);
return;
+ } else {
+ spin_unlock_irqrestore(&acm->read_lock, flags);
+ dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
}
}
+ spin_lock_irqsave(&acm->read_lock, flags);
+ acm->processing = 0;
+ spin_unlock_irqrestore(&acm->read_lock, flags);
}
/* data interface wrote those outgoing bytes */
@@ -463,6 +509,27 @@ static void acm_softint(struct work_struct *work)
tty_wakeup(acm->tty);
}
+static void acm_waker(struct work_struct *waker)
+{
+ struct acm *acm = container_of(waker, struct acm, waker);
+ long flags;
+ int rv;
+
+ rv = usb_autopm_get_interface(acm->control);
+ if (rv < 0) {
+ err("Autopm failure in %s", __func__);
+ return;
+ }
+ if (acm->delayed_wb) {
+ acm_start_wb(acm, acm->delayed_wb);
+ acm->delayed_wb = NULL;
+ }
+ spin_lock_irqsave(&acm->write_lock, flags);
+ acm->write_ready = acm->old_ready;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ usb_autopm_put_interface(acm->control);
+}
+
/*
* TTY handlers
*/
@@ -492,6 +559,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
if (usb_autopm_get_interface(acm->control) < 0)
goto early_bail;
+ else
+ acm->control->needs_remote_wakeup = 1;
mutex_lock(&acm->mutex);
if (acm->used++) {
@@ -509,6 +578,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
(acm->ctrl_caps & USB_CDC_CAP_LINE))
goto full_bailout;
+ usb_autopm_put_interface(acm->control);
INIT_LIST_HEAD(&acm->spare_read_urbs);
INIT_LIST_HEAD(&acm->spare_read_bufs);
@@ -570,12 +640,14 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
mutex_lock(&open_mutex);
if (!--acm->used) {
if (acm->dev) {
+ usb_autopm_get_interface(acm->control);
acm_set_control(acm, acm->ctrlout = 0);
usb_kill_urb(acm->ctrlurb);
for (i = 0; i < ACM_NW; i++)
usb_kill_urb(acm->wb[i].urb);
for (i = 0; i < nr; i++)
usb_kill_urb(acm->ru[i].urb);
+ acm->control->needs_remote_wakeup = 0;
usb_autopm_put_interface(acm->control);
} else
acm_tty_unregister(acm);
@@ -660,13 +732,16 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
tasklet_schedule(&acm->urb_task);
}
-static void acm_tty_break_ctl(struct tty_struct *tty, int state)
+static int acm_tty_break_ctl(struct tty_struct *tty, int state)
{
struct acm *acm = tty->driver_data;
+ int retval;
if (!ACM_READY(acm))
- return;
- if (acm_send_break(acm, state ? 0xffff : 0))
+ return -EINVAL;
+ retval = acm_send_break(acm, state ? 0xffff : 0);
+ if (retval < 0)
dbg("send break failed");
+ return retval;
}
static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
@@ -766,7 +841,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios
* USB probe and disconnect routines.
*/
-/* Little helper: write buffers free */
+/* Little helpers: write/read buffers free */
static void acm_write_buffers_free(struct acm *acm)
{
int i;
@@ -777,6 +852,15 @@ static void acm_write_buffers_free(struct acm *acm)
}
}
+static void acm_read_buffers_free(struct acm *acm)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(acm->control);
+ int i, n = acm->rx_buflimit;
+
+ for (i = 0; i < n; i++)
+ usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+}
+
/* Little helper: write buffers allocate */
static int acm_write_buffers_alloc(struct acm *acm)
{
@@ -987,6 +1071,7 @@ skip_normal_probe:
acm->urb_task.func = acm_rx_tasklet;
acm->urb_task.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint);
+ INIT_WORK(&acm->waker, acm_waker);
spin_lock_init(&acm->throttle_lock);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
@@ -1098,8 +1183,7 @@ alloc_fail8:
for (i = 0; i < ACM_NW; i++)
usb_free_urb(acm->wb[i].urb);
alloc_fail7:
- for (i = 0; i < num_rx_buf; i++)
- usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+ acm_read_buffers_free(acm);
for (i = 0; i < num_rx_buf; i++)
usb_free_urb(acm->ru[i].urb);
usb_free_urb(acm->ctrlurb);
@@ -1116,6 +1200,7 @@ alloc_fail:
static void stop_data_traffic(struct acm *acm)
{
int i;
+ dbg("Entering stop_data_traffic");
tasklet_disable(&acm->urb_task);
@@ -1128,21 +1213,16 @@ static void stop_data_traffic(struct acm *acm)
tasklet_enable(&acm->urb_task);
cancel_work_sync(&acm->work);
+ cancel_work_sync(&acm->waker);
}
static void acm_disconnect(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata(intf);
struct usb_device *usb_dev = interface_to_usbdev(intf);
- int i;
-
- if (!acm || !acm->dev) {
- dbg("disconnect on nonexisting interface");
- return;
- }
mutex_lock(&open_mutex);
- if (!usb_get_intfdata(intf)) {
+ if (!acm || !acm->dev) {
mutex_unlock(&open_mutex);
return;
}
@@ -1161,10 +1241,10 @@ static void acm_disconnect(struct usb_interface *intf)
acm_write_buffers_free(acm);
usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
- for (i = 0; i < acm->rx_buflimit; i++)
- usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+ acm_read_buffers_free(acm);
- usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
+ usb_driver_release_interface(&acm_driver, intf == acm->control ?
+ acm->data : acm->control);
if (!acm->used) {
acm_tty_unregister(acm);
@@ -1178,11 +1258,31 @@ static void acm_disconnect(struct usb_interface *intf)
tty_hangup(acm->tty);
}
+#ifdef CONFIG_PM
static int acm_suspend(struct usb_interface *intf, pm_message_t message)
{
struct acm *acm = usb_get_intfdata(intf);
+ int cnt;
+
+ if (acm->dev->auto_pm) {
+ int b;
+
+ spin_lock_irq(&acm->read_lock);
+ spin_lock(&acm->write_lock);
+ b = acm->processing + acm->transmitting;
+ spin_unlock(&acm->write_lock);
+ spin_unlock_irq(&acm->read_lock);
+ if (b)
+ return -EBUSY;
+ }
+
+ spin_lock_irq(&acm->read_lock);
+ spin_lock(&acm->write_lock);
+ cnt = acm->susp_count++;
+ spin_unlock(&acm->write_lock);
+ spin_unlock_irq(&acm->read_lock);
- if (acm->susp_count++)
+ if (cnt)
return 0;
/*
we treat opened interfaces differently,
@@ -1201,15 +1301,21 @@ static int acm_resume(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata(intf);
int rv = 0;
+ int cnt;
+
+ spin_lock_irq(&acm->read_lock);
+ acm->susp_count -= 1;
+ cnt = acm->susp_count;
+ spin_unlock_irq(&acm->read_lock);
- if (--acm->susp_count)
+ if (cnt)
return 0;
mutex_lock(&acm->mutex);
if (acm->used) {
rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
if (rv < 0)
- goto err_out;
+ goto err_out;
tasklet_schedule(&acm->urb_task);
}
@@ -1218,6 +1324,8 @@ err_out:
mutex_unlock(&acm->mutex);
return rv;
}
+
+#endif /* CONFIG_PM */
/*
* USB driver structure.
*/
@@ -1273,10 +1381,14 @@ static struct usb_driver acm_driver = {
.name = "cdc_acm",
.probe = acm_probe,
.disconnect = acm_disconnect,
+#ifdef CONFIG_PM
.suspend = acm_suspend,
.resume = acm_resume,
+#endif
.id_table = acm_ids,
+#ifdef CONFIG_PM
.supports_autosuspend = 1,
+#endif
};
/*
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 046e064b033..85c3aaaab7c 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -107,10 +107,14 @@ struct acm {
struct list_head filled_read_bufs;
int write_used; /* number of non-empty write buffers */
int write_ready; /* write urb is not running */
+ int old_ready;
+ int processing;
+ int transmitting;
spinlock_t write_lock;
struct mutex mutex;
struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
+ struct work_struct waker;
struct tasklet_struct urb_task; /* rx processing */
spinlock_t throttle_lock; /* synchronize throtteling and read callback */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
@@ -123,6 +127,7 @@ struct acm {
unsigned char clocal; /* termios CLOCAL */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */
+ struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
};
#define CDC_DATA_INTERFACE_TYPE 0x0a
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 731db051070..7e8e1235e4e 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -28,8 +28,9 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.02"
+#define DRIVER_VERSION "v0.03"
#define DRIVER_AUTHOR "Oliver Neukum"
+#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
static struct usb_device_id wdm_ids[] = {
{
@@ -87,6 +88,7 @@ struct wdm_device {
dma_addr_t ihandle;
struct mutex wlock;
struct mutex rlock;
+ struct mutex plock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
@@ -205,7 +207,7 @@ static void wdm_int_callback(struct urb *urb)
req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
req->wValue = 0;
req->wIndex = desc->inum;
- req->wLength = cpu_to_le16(desc->bMaxPacketSize0);
+ req->wLength = cpu_to_le16(desc->wMaxCommand);
usb_fill_control_urb(
desc->response,
@@ -214,7 +216,7 @@ static void wdm_int_callback(struct urb *urb)
usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
(unsigned char *)req,
desc->inbuf,
- desc->bMaxPacketSize0,
+ desc->wMaxCommand,
wdm_in_callback,
desc
);
@@ -247,6 +249,7 @@ exit:
static void kill_urbs(struct wdm_device *desc)
{
+ /* the order here is essential */
usb_kill_urb(desc->command);
usb_kill_urb(desc->validity);
usb_kill_urb(desc->response);
@@ -266,7 +269,7 @@ static void cleanup(struct wdm_device *desc)
desc->sbuf,
desc->validity->transfer_dma);
usb_buffer_free(interface_to_usbdev(desc->intf),
- desc->wMaxPacketSize,
+ desc->wMaxCommand,
desc->inbuf,
desc->response->transfer_dma);
kfree(desc->orq);
@@ -299,6 +302,9 @@ static ssize_t wdm_write
if (r)
goto outnl;
+ r = usb_autopm_get_interface(desc->intf);
+ if (r < 0)
+ goto outnp;
r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
&desc->flags));
if (r < 0)
@@ -347,11 +353,14 @@ static ssize_t wdm_write
if (rv < 0) {
kfree(buf);
clear_bit(WDM_IN_USE, &desc->flags);
+ err("Tx URB error: %d", rv);
} else {
dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
req->wIndex);
}
out:
+ usb_autopm_put_interface(desc->intf);
+outnp:
mutex_unlock(&desc->wlock);
outnl:
return rv < 0 ? rv : count;
@@ -376,6 +385,11 @@ retry:
rv = wait_event_interruptible(desc->wait,
test_bit(WDM_READ, &desc->flags));
+ if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+ rv = -ENODEV;
+ goto err;
+ }
+ usb_mark_last_busy(interface_to_usbdev(desc->intf));
if (rv < 0) {
rv = -ERESTARTSYS;
goto err;
@@ -418,6 +432,9 @@ retry:
desc->ubuf[i] = desc->ubuf[i + cntr];
desc->length -= cntr;
+ /* in case we had outstanding data */
+ if (!desc->length)
+ clear_bit(WDM_READ, &desc->flags);
rv = cntr;
err:
@@ -480,18 +497,28 @@ static int wdm_open(struct inode *inode, struct file *file)
if (test_bit(WDM_DISCONNECTING, &desc->flags))
goto out;
- desc->count++;
+ ;
file->private_data = desc;
- rv = usb_submit_urb(desc->validity, GFP_KERNEL);
-
+ rv = usb_autopm_get_interface(desc->intf);
if (rv < 0) {
- desc->count--;
- err("Error submitting int urb - %d", rv);
+ err("Error autopm - %d", rv);
goto out;
}
- rv = 0;
+ intf->needs_remote_wakeup = 1;
+ mutex_lock(&desc->plock);
+ if (!desc->count++) {
+ rv = usb_submit_urb(desc->validity, GFP_KERNEL);
+ if (rv < 0) {
+ desc->count--;
+ err("Error submitting int urb - %d", rv);
+ }
+ } else {
+ rv = 0;
+ }
+ mutex_unlock(&desc->plock);
+ usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
return rv;
@@ -502,10 +529,15 @@ static int wdm_release(struct inode *inode, struct file *file)
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
+ mutex_lock(&desc->plock);
desc->count--;
+ mutex_unlock(&desc->plock);
+
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
kill_urbs(desc);
+ if (!test_bit(WDM_DISCONNECTING, &desc->flags))
+ desc->intf->needs_remote_wakeup = 0;
}
mutex_unlock(&wdm_mutex);
return 0;
@@ -597,6 +629,7 @@ next_desc:
goto out;
mutex_init(&desc->wlock);
mutex_init(&desc->rlock);
+ mutex_init(&desc->plock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
@@ -698,6 +731,7 @@ static void wdm_disconnect(struct usb_interface *intf)
spin_lock_irqsave(&desc->iuspin, flags);
set_bit(WDM_DISCONNECTING, &desc->flags);
set_bit(WDM_READ, &desc->flags);
+ /* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
cancel_work_sync(&desc->rxwork);
@@ -708,11 +742,81 @@ static void wdm_disconnect(struct usb_interface *intf)
mutex_unlock(&wdm_mutex);
}
+static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct wdm_device *desc = usb_get_intfdata(intf);
+ int rv = 0;
+
+ dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
+
+ mutex_lock(&desc->plock);
+#ifdef CONFIG_PM
+ if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) {
+ rv = -EBUSY;
+ } else {
+#endif
+ cancel_work_sync(&desc->rxwork);
+ kill_urbs(desc);
+#ifdef CONFIG_PM
+ }
+#endif
+ mutex_unlock(&desc->plock);
+
+ return rv;
+}
+
+static int recover_from_urb_loss(struct wdm_device *desc)
+{
+ int rv = 0;
+
+ if (desc->count) {
+ rv = usb_submit_urb(desc->validity, GFP_NOIO);
+ if (rv < 0)
+ err("Error resume submitting int urb - %d", rv);
+ }
+ return rv;
+}
+static int wdm_resume(struct usb_interface *intf)
+{
+ struct wdm_device *desc = usb_get_intfdata(intf);
+ int rv;
+
+ dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
+ mutex_lock(&desc->plock);
+ rv = recover_from_urb_loss(desc);
+ mutex_unlock(&desc->plock);
+ return rv;
+}
+
+static int wdm_pre_reset(struct usb_interface *intf)
+{
+ struct wdm_device *desc = usb_get_intfdata(intf);
+
+ mutex_lock(&desc->plock);
+ return 0;
+}
+
+static int wdm_post_reset(struct usb_interface *intf)
+{
+ struct wdm_device *desc = usb_get_intfdata(intf);
+ int rv;
+
+ rv = recover_from_urb_loss(desc);
+ mutex_unlock(&desc->plock);
+ return 0;
+}
+
static struct usb_driver wdm_driver = {
.name = "cdc_wdm",
.probe = wdm_probe,
.disconnect = wdm_disconnect,
+ .suspend = wdm_suspend,
+ .resume = wdm_resume,
+ .reset_resume = wdm_resume,
+ .pre_reset = wdm_pre_reset,
+ .post_reset = wdm_post_reset,
.id_table = wdm_ids,
+ .supports_autosuspend = 1,
};
/* --- low level module stuff --- */
@@ -735,6 +839,5 @@ module_init(wdm_init);
module_exit(wdm_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION("USB Abstract Control Model driver for "
- "USB WCM Device Management");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 83d9dc379d9..6ec38175a81 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -46,8 +46,6 @@
* 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
* Converted file reading routine to dump to buffer once
* per device, not per bus
- *
- * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
*/
#include <linux/fs.h>
@@ -63,8 +61,6 @@
#include "usb.h"
#include "hcd.h"
-#define MAX_TOPO_LEVEL 6
-
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 9218cca2104..20290c5b156 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -19,8 +19,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
- *
* This file implements the usbfs/x/y files, where
* x is the bus number and y the device number.
*
@@ -61,6 +59,22 @@
/* Mutual exclusion for removal, open, and release */
DEFINE_MUTEX(usbfs_mutex);
+struct dev_state {
+ struct list_head list; /* state list */
+ struct usb_device *dev;
+ struct file *file;
+ spinlock_t lock; /* protects the async urb lists */
+ struct list_head async_pending;
+ struct list_head async_completed;
+ wait_queue_head_t wait; /* wake up if a request completed */
+ unsigned int discsignr;
+ struct pid *disc_pid;
+ uid_t disc_uid, disc_euid;
+ void __user *disccontext;
+ unsigned long ifclaimed;
+ u32 secid;
+};
+
struct async {
struct list_head asynclist;
struct dev_state *ps;
@@ -536,23 +550,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
return ret;
}
-static int __match_minor(struct device *dev, void *data)
+static int match_devt(struct device *dev, void *data)
{
- int minor = *((int *)data);
-
- if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
- return 1;
- return 0;
+ return dev->devt == (dev_t) (unsigned long) data;
}
-static struct usb_device *usbdev_lookup_by_minor(int minor)
+static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
{
struct device *dev;
- dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
+ dev = bus_find_device(&usb_bus_type, NULL,
+ (void *) (unsigned long) devt, match_devt);
if (!dev)
return NULL;
- put_device(dev);
return container_of(dev, struct usb_device, dev);
}
@@ -575,21 +585,27 @@ static int usbdev_open(struct inode *inode, struct file *file)
goto out;
ret = -ENOENT;
+
/* usbdev device-node */
if (imajor(inode) == USB_DEVICE_MAJOR)
- dev = usbdev_lookup_by_minor(iminor(inode));
+ dev = usbdev_lookup_by_devt(inode->i_rdev);
#ifdef CONFIG_USB_DEVICEFS
/* procfs file */
- if (!dev)
+ if (!dev) {
dev = inode->i_private;
+ if (dev && dev->usbfs_dentry &&
+ dev->usbfs_dentry->d_inode == inode)
+ usb_get_dev(dev);
+ else
+ dev = NULL;
+ }
#endif
- if (!dev)
+ if (!dev || dev->state == USB_STATE_NOTATTACHED)
goto out;
ret = usb_autoresume_device(dev);
if (ret)
goto out;
- usb_get_dev(dev);
ret = 0;
ps->dev = dev;
ps->file = file;
@@ -609,8 +625,10 @@ static int usbdev_open(struct inode *inode, struct file *file)
list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps;
out:
- if (ret)
+ if (ret) {
kfree(ps);
+ usb_put_dev(dev);
+ }
mutex_unlock(&usbfs_mutex);
unlock_kernel();
return ret;
@@ -874,7 +892,7 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg)
static int proc_resetdevice(struct dev_state *ps)
{
- return usb_reset_composite_device(ps->dev, NULL);
+ return usb_reset_device(ps->dev);
}
static int proc_setintf(struct dev_state *ps, void __user *arg)
@@ -1682,25 +1700,49 @@ const struct file_operations usbdev_file_operations = {
.release = usbdev_release,
};
+void usb_fs_classdev_common_remove(struct usb_device *udev)
+{
+ struct dev_state *ps;
+ struct siginfo sinfo;
+
+ while (!list_empty(&udev->filelist)) {
+ ps = list_entry(udev->filelist.next, struct dev_state, list);
+ destroy_all_async(ps);
+ wake_up_all(&ps->wait);
+ list_del_init(&ps->list);
+ if (ps->discsignr) {
+ sinfo.si_signo = ps->discsignr;
+ sinfo.si_errno = EPIPE;
+ sinfo.si_code = SI_ASYNCIO;
+ sinfo.si_addr = ps->disccontext;
+ kill_pid_info_as_uid(ps->discsignr, &sinfo,
+ ps->disc_pid, ps->disc_uid,
+ ps->disc_euid, ps->secid);
+ }
+ }
+}
+
#ifdef CONFIG_USB_DEVICE_CLASS
static struct class *usb_classdev_class;
static int usb_classdev_add(struct usb_device *dev)
{
- int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
-
- dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
- MKDEV(USB_DEVICE_MAJOR, minor),
- "usbdev%d.%d", dev->bus->busnum, dev->devnum);
- if (IS_ERR(dev->usb_classdev))
- return PTR_ERR(dev->usb_classdev);
-
+ struct device *cldev;
+
+ cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
+ dev->dev.devt, NULL, "usbdev%d.%d",
+ dev->bus->busnum, dev->devnum);
+ if (IS_ERR(cldev))
+ return PTR_ERR(cldev);
+ dev->usb_classdev = cldev;
return 0;
}
static void usb_classdev_remove(struct usb_device *dev)
{
- device_unregister(dev->usb_classdev);
+ if (dev->usb_classdev)
+ device_unregister(dev->usb_classdev);
+ usb_fs_classdev_common_remove(dev);
}
static int usb_classdev_notify(struct notifier_block *self,
@@ -1750,6 +1792,11 @@ int __init usb_devio_init(void)
usb_classdev_class = NULL;
goto out;
}
+ /* devices of this class shadow the major:minor of their parent
+ * device, so clear ->dev_kobj to prevent adding duplicate entries
+ * to /sys/dev
+ */
+ usb_classdev_class->dev_kobj = NULL;
usb_register_notify(&usbdev_nb);
#endif
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 1e56f1cfa6d..ddb54e14a5c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -201,6 +201,7 @@ static int usb_probe_interface(struct device *dev)
intf = to_usb_interface(dev);
udev = interface_to_usbdev(intf);
+ intf->needs_binding = 0;
if (udev->authorized == 0) {
dev_err(&intf->dev, "Device is not authorized for usage\n");
@@ -257,15 +258,16 @@ static int usb_unbind_interface(struct device *dev)
udev = interface_to_usbdev(intf);
error = usb_autoresume_device(udev);
- /* release all urbs for this interface */
- usb_disable_interface(interface_to_usbdev(intf), intf);
+ /* Terminate all URBs for this interface unless the driver
+ * supports "soft" unbinding.
+ */
+ if (!driver->soft_unbind)
+ usb_disable_interface(udev, intf);
driver->disconnect(intf);
/* reset other interface state */
- usb_set_interface(interface_to_usbdev(intf),
- intf->altsetting[0].desc.bInterfaceNumber,
- 0);
+ usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
@@ -310,6 +312,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
dev->driver = &driver->drvwrap.driver;
usb_set_intfdata(iface, priv);
+ iface->needs_binding = 0;
usb_pm_lock(udev);
iface->condition = USB_INTERFACE_BOUND;
@@ -586,7 +589,7 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
struct usb_device *usb_dev;
/* driver is often null here; dev_dbg() would oops */
- pr_debug("usb %s: uevent\n", dev->bus_id);
+ pr_debug("usb %s: uevent\n", dev_name(dev));
if (is_usb_device(dev))
usb_dev = to_usb_device(dev);
@@ -596,11 +599,11 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
}
if (usb_dev->devnum < 0) {
- pr_debug("usb %s: already deleted?\n", dev->bus_id);
+ pr_debug("usb %s: already deleted?\n", dev_name(dev));
return -ENODEV;
}
if (!usb_dev->bus) {
- pr_debug("usb %s: bus removed?\n", dev->bus_id);
+ pr_debug("usb %s: bus removed?\n", dev_name(dev));
return -ENODEV;
}
@@ -771,6 +774,104 @@ void usb_deregister(struct usb_driver *driver)
}
EXPORT_SYMBOL_GPL(usb_deregister);
+
+/* Forced unbinding of a USB interface driver, either because
+ * it doesn't support pre_reset/post_reset/reset_resume or
+ * because it doesn't support suspend/resume.
+ *
+ * The caller must hold @intf's device's lock, but not its pm_mutex
+ * and not @intf->dev.sem.
+ */
+void usb_forced_unbind_intf(struct usb_interface *intf)
+{
+ struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+
+ dev_dbg(&intf->dev, "forced unbind\n");
+ usb_driver_release_interface(driver, intf);
+
+ /* Mark the interface for later rebinding */
+ intf->needs_binding = 1;
+}
+
+/* Delayed forced unbinding of a USB interface driver and scan
+ * for rebinding.
+ *
+ * The caller must hold @intf's device's lock, but not its pm_mutex
+ * and not @intf->dev.sem.
+ *
+ * FIXME: The caller must block system sleep transitions.
+ */
+void usb_rebind_intf(struct usb_interface *intf)
+{
+ int rc;
+
+ /* Delayed unbind of an existing driver */
+ if (intf->dev.driver) {
+ struct usb_driver *driver =
+ to_usb_driver(intf->dev.driver);
+
+ dev_dbg(&intf->dev, "forced unbind\n");
+ usb_driver_release_interface(driver, intf);
+ }
+
+ /* Try to rebind the interface */
+ intf->needs_binding = 0;
+ rc = device_attach(&intf->dev);
+ if (rc < 0)
+ dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+}
+
+#define DO_UNBIND 0
+#define DO_REBIND 1
+
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
+ * or rebind interfaces that have been unbound, according to @action.
+ *
+ * The caller must hold @udev's device lock.
+ * FIXME: For rebinds, the caller must block system sleep transitions.
+ */
+static void do_unbind_rebind(struct usb_device *udev, int action)
+{
+ struct usb_host_config *config;
+ int i;
+ struct usb_interface *intf;
+ struct usb_driver *drv;
+
+ config = udev->actconfig;
+ if (config) {
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ intf = config->interface[i];
+ switch (action) {
+ case DO_UNBIND:
+ if (intf->dev.driver) {
+ drv = to_usb_driver(intf->dev.driver);
+ if (!drv->suspend || !drv->resume)
+ usb_forced_unbind_intf(intf);
+ }
+ break;
+ case DO_REBIND:
+ if (intf->needs_binding) {
+
+ /* FIXME: The next line is needed because we are going to probe
+ * the interface, but as far as the PM core is concerned the
+ * interface is still suspended. The problem wouldn't exist
+ * if we could rebind the interface during the interface's own
+ * resume() call, but at the time the usb_device isn't locked!
+ *
+ * The real solution will be to carry this out during the device's
+ * complete() callback. Until that is implemented, we have to
+ * use this hack.
+ */
+// intf->dev.power.sleeping = 0;
+
+ usb_rebind_intf(intf);
+ }
+ break;
+ }
+ }
+ }
+}
+
#ifdef CONFIG_PM
/* Caller has locked udev's pm_mutex */
@@ -805,8 +906,6 @@ static int usb_resume_device(struct usb_device *udev)
if (udev->state == USB_STATE_NOTATTACHED)
goto done;
- if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
- goto done;
/* Can't resume it if it doesn't have a driver. */
if (udev->dev.driver == NULL) {
@@ -842,7 +941,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
goto done;
driver = to_usb_driver(intf->dev.driver);
- if (driver->suspend && driver->resume) {
+ if (driver->suspend) {
status = driver->suspend(intf, msg);
if (status == 0)
mark_quiesced(intf);
@@ -850,12 +949,10 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
dev_err(&intf->dev, "%s error %d\n",
"suspend", status);
} else {
- /*
- * FIXME else if there's no suspend method, disconnect...
- * Not possible if auto_pm is set...
- */
- dev_warn(&intf->dev, "no suspend for driver %s?\n",
- driver->name);
+ /* Later we will unbind the driver and reprobe */
+ intf->needs_binding = 1;
+ dev_warn(&intf->dev, "no %s for driver %s?\n",
+ "suspend", driver->name);
mark_quiesced(intf);
}
@@ -879,10 +976,12 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
goto done;
/* Can't resume it if it doesn't have a driver. */
- if (intf->condition == USB_INTERFACE_UNBOUND) {
- status = -ENOTCONN;
+ if (intf->condition == USB_INTERFACE_UNBOUND)
+ goto done;
+
+ /* Don't resume if the interface is marked for rebinding */
+ if (intf->needs_binding)
goto done;
- }
driver = to_usb_driver(intf->dev.driver);
if (reset_resume) {
@@ -892,7 +991,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
dev_err(&intf->dev, "%s error %d\n",
"reset_resume", status);
} else {
- /* status = -EOPNOTSUPP; */
+ intf->needs_binding = 1;
dev_warn(&intf->dev, "no %s for driver %s?\n",
"reset_resume", driver->name);
}
@@ -903,7 +1002,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
dev_err(&intf->dev, "%s error %d\n",
"resume", status);
} else {
- /* status = -EOPNOTSUPP; */
+ intf->needs_binding = 1;
dev_warn(&intf->dev, "no %s for driver %s?\n",
"resume", driver->name);
}
@@ -911,11 +1010,10 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
done:
dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
- if (status == 0)
+ if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
mark_active(intf);
- /* FIXME: Unbind the driver and reprobe if the resume failed
- * (not possible if auto_pm is set) */
+ /* Later we will unbind the driver and/or reprobe, if necessary */
return status;
}
@@ -1173,11 +1271,8 @@ static int usb_resume_both(struct usb_device *udev)
* then we're stuck. */
status = usb_resume_device(udev);
}
- } else {
-
- /* Needed for reset-resume */
+ } else if (udev->reset_resume)
status = usb_resume_device(udev);
- }
if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
@@ -1474,6 +1569,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
{
int status;
+ do_unbind_rebind(udev, DO_UNBIND);
usb_pm_lock(udev);
udev->auto_pm = 0;
status = usb_suspend_both(udev, msg);
@@ -1501,6 +1597,7 @@ int usb_external_resume_device(struct usb_device *udev)
status = usb_resume_both(udev);
udev->last_busy = jiffies;
usb_pm_unlock(udev);
+ do_unbind_rebind(udev, DO_REBIND);
/* Now that the device is awake, we can start trying to autosuspend
* it again. */
@@ -1542,14 +1639,11 @@ static int usb_resume(struct device *dev)
udev = to_usb_device(dev);
/* If udev->skip_sys_resume is set then udev was already suspended
- * when the system suspend started, so we don't want to resume
- * udev during this system wakeup. However a reset-resume counts
- * as a wakeup event, so allow a reset-resume to occur if remote
- * wakeup is enabled. */
- if (udev->skip_sys_resume) {
- if (!(udev->reset_resume && udev->do_remote_wakeup))
- return -EHOSTUNREACH;
- }
+ * when the system sleep started, so we don't want to resume it
+ * during this system wakeup.
+ */
+ if (udev->skip_sys_resume)
+ return 0;
return usb_external_resume_device(udev);
}
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index fae55a31e26..22912136fc1 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -296,7 +296,7 @@ int usb_create_ep_files(struct device *parent,
retval = endpoint_get_minor(ep_dev);
if (retval) {
dev_err(parent, "can not allocate minor number for %s\n",
- ep_dev->dev.bus_id);
+ dev_name(&ep_dev->dev));
goto error_register;
}
@@ -307,7 +307,7 @@ int usb_create_ep_files(struct device *parent,
ep_dev->dev.class = ep_class->class;
ep_dev->dev.parent = parent;
ep_dev->dev.release = ep_device_release;
- snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x",
+ dev_set_name(&ep_dev->dev, "usbdev%d.%d_ep%02x",
udev->bus->busnum, udev->devnum,
endpoint->desc.bEndpointAddress);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index c6a95395e52..6b1b229e38c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -150,7 +150,7 @@ int usb_register_dev(struct usb_interface *intf,
int retval = -EINVAL;
int minor_base = class_driver->minor_base;
int minor = 0;
- char name[BUS_ID_SIZE];
+ char name[20];
char *temp;
#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -190,14 +190,15 @@ int usb_register_dev(struct usb_interface *intf,
intf->minor = minor;
/* create a usb class device for this usb interface */
- snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
+ snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
temp = strrchr(name, '/');
- if (temp && (temp[1] != 0x00))
+ if (temp && (temp[1] != '\0'))
++temp;
else
temp = name;
- intf->usb_dev = device_create(usb_class->class, &intf->dev,
- MKDEV(USB_MAJOR, minor), "%s", temp);
+ intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
+ MKDEV(USB_MAJOR, minor), NULL,
+ "%s", temp);
if (IS_ERR(intf->usb_dev)) {
down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
@@ -227,7 +228,7 @@ void usb_deregister_dev(struct usb_interface *intf,
struct usb_class_driver *class_driver)
{
int minor_base = class_driver->minor_base;
- char name[BUS_ID_SIZE];
+ char name[20];
#ifdef CONFIG_USB_DYNAMIC_MINORS
minor_base = 0;
@@ -242,7 +243,7 @@ void usb_deregister_dev(struct usb_interface *intf,
usb_minors[intf->minor] = NULL;
up_write(&minor_rwsem);
- snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
+ snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base);
device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
intf->usb_dev = NULL;
intf->minor = -1;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 42a436478b7..f7bfd72ef11 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -900,14 +900,14 @@ static int register_root_hub(struct usb_hcd *hcd)
if (retval != sizeof usb_dev->descriptor) {
mutex_unlock(&usb_bus_list_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
- usb_dev->dev.bus_id, retval);
+ dev_name(&usb_dev->dev), retval);
return (retval < 0) ? retval : -EMSGSIZE;
}
retval = usb_new_device (usb_dev);
if (retval) {
dev_err (parent_dev, "can't register root hub for %s, %d\n",
- usb_dev->dev.bus_id, retval);
+ dev_name(&usb_dev->dev), retval);
}
mutex_unlock(&usb_bus_list_lock);
@@ -1764,7 +1764,7 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
* If memory is unavailable, returns NULL.
*/
struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
- struct device *dev, char *bus_name)
+ struct device *dev, const char *bus_name)
{
struct usb_hcd *hcd;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index b9de1569b39..5b0b59b0d89 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -21,6 +21,8 @@
#include <linux/rwsem.h>
+#define MAX_TOPO_LEVEL 6
+
/* This file contains declarations of usbcore internals that are mostly
* used or exposed by Host Controller Drivers.
*/
@@ -235,7 +237,7 @@ extern void usb_hcd_disable_endpoint(struct usb_device *udev,
extern int usb_hcd_get_frame_number(struct usb_device *udev);
extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
- struct device *dev, char *bus_name);
+ struct device *dev, const char *bus_name);
extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
extern void usb_put_hcd(struct usb_hcd *hcd);
extern int usb_add_hcd(struct usb_hcd *hcd,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 4cfe32a16c3..107e1d25dde 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -72,7 +72,6 @@ struct usb_hub {
unsigned limited_power:1;
unsigned quiescing:1;
- unsigned activating:1;
unsigned disconnected:1;
unsigned has_indicators:1;
@@ -131,6 +130,12 @@ MODULE_PARM_DESC(use_both_schemes,
DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
+#define HUB_DEBOUNCE_TIMEOUT 1500
+#define HUB_DEBOUNCE_STEP 25
+#define HUB_DEBOUNCE_STABLE 100
+
+
+static int usb_reset_and_verify_device(struct usb_device *udev);
static inline char *portspeed(int portstatus)
{
@@ -535,37 +540,6 @@ static void hub_power_on(struct usb_hub *hub)
msleep(max(pgood_delay, (unsigned) 100));
}
-static void hub_quiesce(struct usb_hub *hub)
-{
- /* (nonblocking) khubd and related activity won't re-trigger */
- hub->quiescing = 1;
- hub->activating = 0;
-
- /* (blocking) stop khubd and related activity */
- usb_kill_urb(hub->urb);
- if (hub->has_indicators)
- cancel_delayed_work_sync(&hub->leds);
- if (hub->tt.hub)
- cancel_work_sync(&hub->tt.kevent);
-}
-
-static void hub_activate(struct usb_hub *hub)
-{
- int status;
-
- hub->quiescing = 0;
- hub->activating = 1;
-
- status = usb_submit_urb(hub->urb, GFP_NOIO);
- if (status < 0)
- dev_err(hub->intfdev, "activate --> %d\n", status);
- if (hub->has_indicators && blinkenlights)
- schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
-
- /* scan all ports ASAP */
- kick_khubd(hub);
-}
-
static int hub_hub_status(struct usb_hub *hub,
u16 *status, u16 *change)
{
@@ -624,136 +598,149 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
kick_khubd(hub);
}
-/* caller has locked the hub device */
-static void hub_stop(struct usb_hub *hub)
+enum hub_activation_type {
+ HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+};
+
+static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
{
struct usb_device *hdev = hub->hdev;
- int i;
+ int port1;
+ int status;
+ bool need_debounce_delay = false;
- /* Disconnect all the children */
- for (i = 0; i < hdev->maxchild; ++i) {
- if (hdev->children[i])
- usb_disconnect(&hdev->children[i]);
- }
- hub_quiesce(hub);
-}
+ /* After a resume, port power should still be on.
+ * For any other type of activation, turn it on.
+ */
+ if (type != HUB_RESUME)
+ hub_power_on(hub);
-#define HUB_RESET 1
-#define HUB_RESUME 2
-#define HUB_RESET_RESUME 3
+ /* Check each port and set hub->change_bits to let khubd know
+ * which ports need attention.
+ */
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ struct usb_device *udev = hdev->children[port1-1];
+ u16 portstatus, portchange;
-#ifdef CONFIG_PM
+ portstatus = portchange = 0;
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+ if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+ dev_dbg(hub->intfdev,
+ "port %d: status %04x change %04x\n",
+ port1, portstatus, portchange);
-/* Try to identify which devices need USB-PERSIST handling */
-static int persistent_device(struct usb_device *udev)
-{
- int i;
- int retval;
- struct usb_host_config *actconfig;
+ /* After anything other than HUB_RESUME (i.e., initialization
+ * or any sort of reset), every port should be disabled.
+ * Unconnected ports should likewise be disabled (paranoia),
+ * and so should ports for which we have no usb_device.
+ */
+ if ((portstatus & USB_PORT_STAT_ENABLE) && (
+ type != HUB_RESUME ||
+ !(portstatus & USB_PORT_STAT_CONNECTION) ||
+ !udev ||
+ udev->state == USB_STATE_NOTATTACHED)) {
+ clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+ portstatus &= ~USB_PORT_STAT_ENABLE;
+ }
- /* Explicitly not marked persistent? */
- if (!udev->persist_enabled)
- return 0;
+ /* Clear status-change flags; we'll debounce later */
+ if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ need_debounce_delay = true;
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_CONNECTION);
+ }
+ if (portchange & USB_PORT_STAT_C_ENABLE) {
+ need_debounce_delay = true;
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_ENABLE);
+ }
- /* No active config? */
- actconfig = udev->actconfig;
- if (!actconfig)
- return 0;
+ if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+ /* Tell khubd to disconnect the device or
+ * check for a new connection
+ */
+ if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+ set_bit(port1, hub->change_bits);
+
+ } else if (portstatus & USB_PORT_STAT_ENABLE) {
+ /* The power session apparently survived the resume.
+ * If there was an overcurrent or suspend change
+ * (i.e., remote wakeup request), have khubd
+ * take care of it.
+ */
+ if (portchange)
+ set_bit(port1, hub->change_bits);
- /* FIXME! We should check whether it's open here or not! */
+ } else if (udev->persist_enabled) {
+#ifdef CONFIG_PM
+ udev->reset_resume = 1;
+#endif
+ set_bit(port1, hub->change_bits);
- /*
- * Check that all the interface drivers have a
- * 'reset_resume' entrypoint
+ } else {
+ /* The power session is gone; tell khubd */
+ usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+ set_bit(port1, hub->change_bits);
+ }
+ }
+
+ /* If no port-status-change flags were set, we don't need any
+ * debouncing. If flags were set we can try to debounce the
+ * ports all at once right now, instead of letting khubd do them
+ * one at a time later on.
+ *
+ * If any port-status changes do occur during this delay, khubd
+ * will see them later and handle them normally.
*/
- retval = 0;
- for (i = 0; i < actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *intf;
- struct usb_driver *driver;
+ if (need_debounce_delay)
+ msleep(HUB_DEBOUNCE_STABLE);
- intf = actconfig->interface[i];
- if (!intf->dev.driver)
- continue;
- driver = to_usb_driver(intf->dev.driver);
- if (!driver->reset_resume)
- return 0;
- /*
- * We have at least one driver, and that one
- * has a reset_resume method.
- */
- retval = 1;
- }
- return retval;
-}
+ hub->quiescing = 0;
-static void hub_restart(struct usb_hub *hub, int type)
-{
- struct usb_device *hdev = hub->hdev;
- int port1;
+ status = usb_submit_urb(hub->urb, GFP_NOIO);
+ if (status < 0)
+ dev_err(hub->intfdev, "activate --> %d\n", status);
+ if (hub->has_indicators && blinkenlights)
+ schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
- /* Check each of the children to see if they require
- * USB-PERSIST handling or disconnection. Also check
- * each unoccupied port to make sure it is still disabled.
- */
- for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- struct usb_device *udev = hdev->children[port1-1];
- int status = 0;
- u16 portstatus, portchange;
+ /* Scan all ports that need attention */
+ kick_khubd(hub);
+}
- if (!udev || udev->state == USB_STATE_NOTATTACHED) {
- if (type != HUB_RESET) {
- status = hub_port_status(hub, port1,
- &portstatus, &portchange);
- if (status == 0 && (portstatus &
- USB_PORT_STAT_ENABLE))
- clear_port_feature(hdev, port1,
- USB_PORT_FEAT_ENABLE);
- }
- continue;
- }
+enum hub_quiescing_type {
+ HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
+};
- /* Was the power session lost while we were suspended? */
- status = hub_port_status(hub, port1, &portstatus, &portchange);
+static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+{
+ struct usb_device *hdev = hub->hdev;
+ int i;
- /* If the device is gone, khubd will handle it later */
- if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION))
- continue;
+ /* khubd and related activity won't re-trigger */
+ hub->quiescing = 1;
- /* For "USB_PERSIST"-enabled children we must
- * mark the child device for reset-resume and
- * turn off the various status changes to prevent
- * khubd from disconnecting it later.
- */
- if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) &&
- persistent_device(udev)) {
- if (portchange & USB_PORT_STAT_C_ENABLE)
- clear_port_feature(hub->hdev, port1,
- USB_PORT_FEAT_C_ENABLE);
- if (portchange & USB_PORT_STAT_C_CONNECTION)
- clear_port_feature(hub->hdev, port1,
- USB_PORT_FEAT_C_CONNECTION);
- udev->reset_resume = 1;
+ if (type != HUB_SUSPEND) {
+ /* Disconnect all the children */
+ for (i = 0; i < hdev->maxchild; ++i) {
+ if (hdev->children[i])
+ usb_disconnect(&hdev->children[i]);
}
-
- /* Otherwise for a reset_resume we must disconnect the child,
- * but as we may not lock the child device here
- * we have to do a "logical" disconnect.
- */
- else if (type == HUB_RESET_RESUME)
- hub_port_logical_disconnect(hub, port1);
}
- hub_activate(hub);
+ /* Stop khubd and related activity */
+ usb_kill_urb(hub->urb);
+ if (hub->has_indicators)
+ cancel_delayed_work_sync(&hub->leds);
+ if (hub->tt.hub)
+ cancel_work_sync(&hub->tt.kevent);
}
-#endif /* CONFIG_PM */
-
/* caller has locked the hub device */
static int hub_pre_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
- hub_stop(hub);
+ hub_quiesce(hub, HUB_PRE_RESET);
return 0;
}
@@ -762,8 +749,7 @@ static int hub_post_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
- hub_power_on(hub);
- hub_activate(hub);
+ hub_activate(hub, HUB_POST_RESET);
return 0;
}
@@ -1009,8 +995,7 @@ static int hub_configure(struct usb_hub *hub,
if (hub->has_indicators && blinkenlights)
hub->indicator [0] = INDICATOR_CYCLE;
- hub_power_on(hub);
- hub_activate(hub);
+ hub_activate(hub, HUB_INIT);
return 0;
fail:
@@ -1042,7 +1027,7 @@ static void hub_disconnect(struct usb_interface *intf)
/* Disconnect all children and quiesce the hub */
hub->error = 0;
- hub_stop(hub);
+ hub_quiesce(hub, HUB_DISCONNECT);
usb_set_intfdata (intf, NULL);
@@ -1068,6 +1053,12 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
+ if (hdev->level == MAX_TOPO_LEVEL) {
+ dev_err(&intf->dev, "Unsupported bus topology: "
+ "hub nested too deep\n");
+ return -E2BIG;
+ }
+
#ifdef CONFIG_USB_OTG_BLACKLIST_HUB
if (hdev->parent) {
dev_warn(&intf->dev, "ignoring external hub\n");
@@ -1814,6 +1805,51 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
#ifdef CONFIG_PM
+#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
+ USB_PORT_STAT_SUSPEND)
+#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
+
+/* Determine whether the device on a port is ready for a normal resume,
+ * is ready for a reset-resume, or should be disconnected.
+ */
+static int check_port_resume_type(struct usb_device *udev,
+ struct usb_hub *hub, int port1,
+ int status, unsigned portchange, unsigned portstatus)
+{
+ /* Is the device still present? */
+ if (status || (portstatus & MASK_BITS) != WANT_BITS) {
+ if (status >= 0)
+ status = -ENODEV;
+ }
+
+ /* Can't do a normal resume if the port isn't enabled,
+ * so try a reset-resume instead.
+ */
+ else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) {
+ if (udev->persist_enabled)
+ udev->reset_resume = 1;
+ else
+ status = -ENODEV;
+ }
+
+ if (status) {
+ dev_dbg(hub->intfdev,
+ "port %d status %04x.%04x after resume, %d\n",
+ port1, portchange, portstatus, status);
+ } else if (udev->reset_resume) {
+
+ /* Late port handoff can set status-change bits */
+ if (portchange & USB_PORT_STAT_C_CONNECTION)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_CONNECTION);
+ if (portchange & USB_PORT_STAT_C_ENABLE)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_ENABLE);
+ }
+
+ return status;
+}
+
#ifdef CONFIG_USB_SUSPEND
/*
@@ -1943,7 +1979,8 @@ static int finish_port_resume(struct usb_device *udev)
* resumed.
*/
if (udev->reset_resume)
- status = usb_reset_device(udev);
+ retry_reset_resume:
+ status = usb_reset_and_verify_device(udev);
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
@@ -1954,6 +1991,13 @@ static int finish_port_resume(struct usb_device *udev)
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
if (status >= 0)
status = (status > 0 ? 0 : -ENODEV);
+
+ /* If a normal resume failed, try doing a reset-resume */
+ if (status && !udev->reset_resume && udev->persist_enabled) {
+ dev_dbg(&udev->dev, "retry with reset-resume\n");
+ udev->reset_resume = 1;
+ goto retry_reset_resume;
+ }
}
if (status) {
@@ -2002,7 +2046,7 @@ static int finish_port_resume(struct usb_device *udev)
* to it will be lost. Using the USB_PERSIST facility, the device can be
* made to appear as if it had not disconnected.
*
- * This facility can be dangerous. Although usb_reset_device() makes
+ * This facility can be dangerous. Although usb_reset_and_verify_device() makes
* every effort to insure that the same device is present after the
* reset as before, it cannot provide a 100% guarantee. Furthermore it's
* quite possible for a device to remain unaltered but its media to be
@@ -2018,7 +2062,6 @@ int usb_port_resume(struct usb_device *udev)
int port1 = udev->portnum;
int status;
u16 portchange, portstatus;
- unsigned mask_flags, want_flags;
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -2047,35 +2090,23 @@ int usb_port_resume(struct usb_device *udev)
*/
status = hub_port_status(hub, port1, &portstatus, &portchange);
- SuspendCleared:
- if (udev->reset_resume)
- want_flags = USB_PORT_STAT_POWER
- | USB_PORT_STAT_CONNECTION;
- else
- want_flags = USB_PORT_STAT_POWER
- | USB_PORT_STAT_CONNECTION
- | USB_PORT_STAT_ENABLE;
- mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+ }
- if (status < 0 || (portstatus & mask_flags) != want_flags) {
- dev_dbg(hub->intfdev,
- "port %d status %04x.%04x after resume, %d\n",
- port1, portchange, portstatus, status);
- if (status >= 0)
- status = -ENODEV;
- } else {
- if (portchange & USB_PORT_STAT_C_SUSPEND)
- clear_port_feature(hub->hdev, port1,
- USB_PORT_FEAT_C_SUSPEND);
- /* TRSMRCY = 10 msec */
- msleep(10);
- }
+ SuspendCleared:
+ if (status == 0) {
+ if (portchange & USB_PORT_STAT_C_SUSPEND)
+ clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_C_SUSPEND);
}
clear_bit(port1, hub->busy_bits);
if (!hub->hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hub->hdev->bus);
+ status = check_port_resume_type(udev,
+ hub, port1, status, portchange, portstatus);
if (status == 0)
status = finish_port_resume(udev);
if (status < 0) {
@@ -2085,17 +2116,16 @@ int usb_port_resume(struct usb_device *udev)
return status;
}
+/* caller has locked udev */
static int remote_wakeup(struct usb_device *udev)
{
int status = 0;
- usb_lock_device(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
usb_mark_last_busy(udev);
status = usb_external_resume_device(udev);
}
- usb_unlock_device(udev);
return status;
}
@@ -2108,14 +2138,25 @@ int usb_port_suspend(struct usb_device *udev)
return 0;
}
+/* However we may need to do a reset-resume */
+
int usb_port_resume(struct usb_device *udev)
{
- int status = 0;
+ struct usb_hub *hub = hdev_to_hub(udev->parent);
+ int port1 = udev->portnum;
+ int status;
+ u16 portchange, portstatus;
- /* However we may need to do a reset-resume */
- if (udev->reset_resume) {
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+ status = check_port_resume_type(udev,
+ hub, port1, status, portchange, portstatus);
+
+ if (status) {
+ dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ hub_port_logical_disconnect(hub, port1);
+ } else if (udev->reset_resume) {
dev_dbg(&udev->dev, "reset-resume\n");
- status = usb_reset_device(udev);
+ status = usb_reset_and_verify_device(udev);
}
return status;
}
@@ -2149,7 +2190,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
dev_dbg(&intf->dev, "%s\n", __func__);
/* stop khubd and related activity */
- hub_quiesce(hub);
+ hub_quiesce(hub, HUB_SUSPEND);
return 0;
}
@@ -2158,7 +2199,7 @@ static int hub_resume(struct usb_interface *intf)
struct usb_hub *hub = usb_get_intfdata(intf);
dev_dbg(&intf->dev, "%s\n", __func__);
- hub_restart(hub, HUB_RESUME);
+ hub_activate(hub, HUB_RESUME);
return 0;
}
@@ -2167,8 +2208,7 @@ static int hub_reset_resume(struct usb_interface *intf)
struct usb_hub *hub = usb_get_intfdata(intf);
dev_dbg(&intf->dev, "%s\n", __func__);
- hub_power_on(hub);
- hub_restart(hub, HUB_RESET_RESUME);
+ hub_activate(hub, HUB_RESET_RESUME);
return 0;
}
@@ -2218,11 +2258,6 @@ static inline int remote_wakeup(struct usb_device *udev)
* every 25ms for transient disconnects. When the port status has been
* unchanged for 100ms it returns the port status.
*/
-
-#define HUB_DEBOUNCE_TIMEOUT 1500
-#define HUB_DEBOUNCE_STEP 25
-#define HUB_DEBOUNCE_STABLE 100
-
static int hub_port_debounce(struct usb_hub *hub, int port1)
{
int ret;
@@ -2302,7 +2337,7 @@ static int hub_set_address(struct usb_device *udev, int devnum)
* Returns device in USB_STATE_ADDRESS, except on error.
*
* If this is called for an already-existing device (as part of
- * usb_reset_device), the caller must own the device lock. For a
+ * usb_reset_and_verify_device), the caller must own the device lock. For a
* newly detected device that is not accessible through any global
* pointers, it's not necessary to lock the device.
*/
@@ -2619,7 +2654,7 @@ hub_power_remaining (struct usb_hub *hub)
* This routine is called when:
* a port connection-change occurs;
* a port enable-change occurs (often caused by EMI);
- * usb_reset_device() encounters changed descriptors (as from
+ * usb_reset_and_verify_device() encounters changed descriptors (as from
* a firmware download)
* caller already locked the hub
*/
@@ -2629,9 +2664,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
struct usb_device *hdev = hub->hdev;
struct device *hub_dev = hub->intfdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
- u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ unsigned wHubCharacteristics =
+ le16_to_cpu(hub->descriptor->wHubCharacteristics);
+ struct usb_device *udev;
int status, i;
-
+
dev_dbg (hub_dev,
"port %d, status %04x, change %04x, %s\n",
port1, portstatus, portchange, portspeed (portstatus));
@@ -2640,30 +2677,73 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
set_port_led(hub, port1, HUB_LED_AUTO);
hub->indicator[port1-1] = INDICATOR_AUTO;
}
-
- /* Disconnect any existing devices under this port */
- if (hdev->children[port1-1])
- usb_disconnect(&hdev->children[port1-1]);
- clear_bit(port1, hub->change_bits);
#ifdef CONFIG_USB_OTG
/* during HNP, don't repeat the debounce */
if (hdev->bus->is_b_host)
- portchange &= ~USB_PORT_STAT_C_CONNECTION;
+ portchange &= ~(USB_PORT_STAT_C_CONNECTION |
+ USB_PORT_STAT_C_ENABLE);
#endif
- if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ /* Try to use the debounce delay for protection against
+ * port-enable changes caused, for example, by EMI.
+ */
+ if (portchange & (USB_PORT_STAT_C_CONNECTION |
+ USB_PORT_STAT_C_ENABLE)) {
status = hub_port_debounce(hub, port1);
if (status < 0) {
if (printk_ratelimit())
dev_err (hub_dev, "connect-debounce failed, "
"port %d disabled\n", port1);
- goto done;
+ portstatus &= ~USB_PORT_STAT_CONNECTION;
+ } else {
+ portstatus = status;
+ }
+ }
+
+ /* Try to resuscitate an existing device */
+ udev = hdev->children[port1-1];
+ if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
+ udev->state != USB_STATE_NOTATTACHED) {
+
+ usb_lock_device(udev);
+ if (portstatus & USB_PORT_STAT_ENABLE) {
+ status = 0; /* Nothing to do */
+ } else if (!udev->persist_enabled) {
+ status = -ENODEV; /* Mustn't resuscitate */
+
+#ifdef CONFIG_USB_SUSPEND
+ } else if (udev->state == USB_STATE_SUSPENDED) {
+ /* For a suspended device, treat this as a
+ * remote wakeup event.
+ */
+ if (udev->do_remote_wakeup)
+ status = remote_wakeup(udev);
+
+ /* Otherwise leave it be; devices can't tell the
+ * difference between suspended and disabled.
+ */
+ else
+ status = 0;
+#endif
+
+ } else {
+ status = usb_reset_device(udev);
+ }
+ usb_unlock_device(udev);
+
+ if (status == 0) {
+ clear_bit(port1, hub->change_bits);
+ return;
}
- portstatus = status;
}
- /* Return now if nothing is connected */
+ /* Disconnect any existing devices under this port */
+ if (udev)
+ usb_disconnect(&hdev->children[port1-1]);
+ clear_bit(port1, hub->change_bits);
+
+ /* Return now if debouncing failed or nothing is connected */
if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
/* maybe switch power back on (e.g. root hub was reset) */
@@ -2677,7 +2757,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
for (i = 0; i < SET_CONFIG_TRIES; i++) {
- struct usb_device *udev;
/* reallocate for each attempt, since references
* to the previous one can escape in various ways
@@ -2858,7 +2937,7 @@ static void hub_events(void)
/* If the hub has died, clean up after it */
if (hdev->state == USB_STATE_NOTATTACHED) {
hub->error = -ENODEV;
- hub_stop(hub);
+ hub_quiesce(hub, HUB_DISCONNECT);
goto loop;
}
@@ -2877,7 +2956,7 @@ static void hub_events(void)
dev_dbg (hub_dev, "resetting for error %d\n",
hub->error);
- ret = usb_reset_composite_device(hdev, intf);
+ ret = usb_reset_device(hdev);
if (ret) {
dev_dbg (hub_dev,
"error resetting hub: %d\n", ret);
@@ -2894,7 +2973,7 @@ static void hub_events(void)
continue;
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&
- !connect_change && !hub->activating)
+ !connect_change)
continue;
ret = hub_port_status(hub, i,
@@ -2902,11 +2981,6 @@ static void hub_events(void)
if (ret < 0)
continue;
- if (hub->activating && !hdev->children[i-1] &&
- (portstatus &
- USB_PORT_STAT_CONNECTION))
- connect_change = 1;
-
if (portchange & USB_PORT_STAT_C_CONNECTION) {
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_CONNECTION);
@@ -2941,11 +3015,16 @@ static void hub_events(void)
}
if (portchange & USB_PORT_STAT_C_SUSPEND) {
+ struct usb_device *udev;
+
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_SUSPEND);
- if (hdev->children[i-1]) {
+ udev = hdev->children[i-1];
+ if (udev) {
+ usb_lock_device(udev);
ret = remote_wakeup(hdev->
children[i-1]);
+ usb_unlock_device(udev);
if (ret < 0)
connect_change = 1;
} else {
@@ -3002,8 +3081,6 @@ static void hub_events(void)
}
}
- hub->activating = 0;
-
/* If this is a root hub, tell the HCD it's okay to
* re-enable port-change interrupts now. */
if (!hdev->parent && !hub->busy_bits[0])
@@ -3172,12 +3249,12 @@ static int descriptors_changed(struct usb_device *udev,
}
/**
- * usb_reset_device - perform a USB port reset to reinitialize a device
+ * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
*
* WARNING - don't use this routine to reset a composite device
* (one with multiple interfaces owned by separate drivers)!
- * Use usb_reset_composite_device() instead.
+ * Use usb_reset_device() instead.
*
* Do a port reset, reassign the device's address, and establish its
* former operating configuration. If the reset fails, or the device's
@@ -3201,7 +3278,7 @@ static int descriptors_changed(struct usb_device *udev,
* holding the device lock because these tasks should always call
* usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
*/
-int usb_reset_device(struct usb_device *udev)
+static int usb_reset_and_verify_device(struct usb_device *udev)
{
struct usb_device *parent_hdev = udev->parent;
struct usb_hub *parent_hub;
@@ -3289,26 +3366,28 @@ re_enumerate:
hub_port_logical_disconnect(parent_hub, port1);
return -ENODEV;
}
-EXPORT_SYMBOL_GPL(usb_reset_device);
/**
- * usb_reset_composite_device - warn interface drivers and perform a USB port reset
+ * usb_reset_device - warn interface drivers and perform a USB port reset
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
- * @iface: interface bound to the driver making the request (optional)
*
* Warns all drivers bound to registered interfaces (using their pre_reset
* method), performs the port reset, and then lets the drivers know that
* the reset is over (using their post_reset method).
*
- * Return value is the same as for usb_reset_device().
+ * Return value is the same as for usb_reset_and_verify_device().
*
* The caller must own the device lock. For example, it's safe to use
* this from a driver probe() routine after downloading new firmware.
* For calls that might not occur during probe(), drivers should lock
* the device using usb_lock_device_for_reset().
+ *
+ * If an interface is currently being probed or disconnected, we assume
+ * its driver knows how to handle resets. For all other interfaces,
+ * if the driver doesn't have pre_reset and post_reset methods then
+ * we attempt to unbind it and rebind afterward.
*/
-int usb_reset_composite_device(struct usb_device *udev,
- struct usb_interface *iface)
+int usb_reset_device(struct usb_device *udev)
{
int ret;
int i;
@@ -3324,40 +3403,47 @@ int usb_reset_composite_device(struct usb_device *udev,
/* Prevent autosuspend during the reset */
usb_autoresume_device(udev);
- if (iface && iface->condition != USB_INTERFACE_BINDING)
- iface = NULL;
-
if (config) {
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
struct usb_interface *cintf = config->interface[i];
struct usb_driver *drv;
+ int unbind = 0;
if (cintf->dev.driver) {
drv = to_usb_driver(cintf->dev.driver);
- if (drv->pre_reset)
- (drv->pre_reset)(cintf);
- /* FIXME: Unbind if pre_reset returns an error or isn't defined */
+ if (drv->pre_reset && drv->post_reset)
+ unbind = (drv->pre_reset)(cintf);
+ else if (cintf->condition ==
+ USB_INTERFACE_BOUND)
+ unbind = 1;
+ if (unbind)
+ usb_forced_unbind_intf(cintf);
}
}
}
- ret = usb_reset_device(udev);
+ ret = usb_reset_and_verify_device(udev);
if (config) {
for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
struct usb_interface *cintf = config->interface[i];
struct usb_driver *drv;
+ int rebind = cintf->needs_binding;
- if (cintf->dev.driver) {
+ if (!rebind && cintf->dev.driver) {
drv = to_usb_driver(cintf->dev.driver);
if (drv->post_reset)
- (drv->post_reset)(cintf);
- /* FIXME: Unbind if post_reset returns an error or isn't defined */
+ rebind = (drv->post_reset)(cintf);
+ else if (cintf->condition ==
+ USB_INTERFACE_BOUND)
+ rebind = 1;
}
+ if (rebind)
+ usb_rebind_intf(cintf);
}
}
usb_autosuspend_device(udev);
return ret;
}
-EXPORT_SYMBOL_GPL(usb_reset_composite_device);
+EXPORT_SYMBOL_GPL(usb_reset_device);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 1d253dd4ea8..db410e92c80 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -712,25 +712,11 @@ static void usbfs_add_device(struct usb_device *dev)
static void usbfs_remove_device(struct usb_device *dev)
{
- struct dev_state *ds;
- struct siginfo sinfo;
-
if (dev->usbfs_dentry) {
fs_remove_file (dev->usbfs_dentry);
dev->usbfs_dentry = NULL;
}
- while (!list_empty(&dev->filelist)) {
- ds = list_entry(dev->filelist.next, struct dev_state, list);
- wake_up_all(&ds->wait);
- list_del_init(&ds->list);
- if (ds->discsignr) {
- sinfo.si_signo = ds->discsignr;
- sinfo.si_errno = EPIPE;
- sinfo.si_code = SI_ASYNCIO;
- sinfo.si_addr = ds->disccontext;
- kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid);
- }
- }
+ usb_fs_classdev_common_remove(dev);
}
static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fe47d145255..2fcc06eb5e6 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -400,7 +400,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
if (usb_pipein(pipe))
urb_flags |= URB_SHORT_NOT_OK;
- for (i = 0; i < io->entries; i++) {
+ for_each_sg(sg, sg, io->entries, i) {
unsigned len;
io->urbs[i] = usb_alloc_urb(0, mem_flags);
@@ -434,17 +434,17 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
* to prevent stale pointers and to help spot bugs.
*/
if (dma) {
- io->urbs[i]->transfer_dma = sg_dma_address(sg + i);
- len = sg_dma_len(sg + i);
+ io->urbs[i]->transfer_dma = sg_dma_address(sg);
+ len = sg_dma_len(sg);
#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
io->urbs[i]->transfer_buffer = NULL;
#else
- io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
+ io->urbs[i]->transfer_buffer = sg_virt(sg);
#endif
} else {
/* hc may use _only_ transfer_buffer */
- io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
- len = sg[i].length;
+ io->urbs[i]->transfer_buffer = sg_virt(sg);
+ len = sg->length;
}
if (length) {
@@ -1090,7 +1090,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if (!device_is_registered(&interface->dev))
continue;
dev_dbg(&dev->dev, "unregistering interface %s\n",
- interface->dev.bus_id);
+ dev_name(&interface->dev));
device_del(&interface->dev);
usb_remove_sysfs_intf_files(interface);
}
@@ -1476,7 +1476,7 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
*
* This call is synchronous. The calling context must be able to sleep,
* must own the device lock, and must not hold the driver model's USB
- * bus mutex; usb device driver probe() methods cannot use this routine.
+ * bus mutex; usb interface driver probe() methods cannot use this routine.
*
* Returns zero on success, or else the status code returned by the
* underlying call that failed. On successful completion, each interface
@@ -1611,7 +1611,7 @@ free_interfaces:
intf->dev.dma_mask = dev->dev.dma_mask;
device_initialize(&intf->dev);
mark_quiesced(intf);
- sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",
+ dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber);
}
@@ -1631,12 +1631,12 @@ free_interfaces:
dev_dbg(&dev->dev,
"adding %s (config #%d, interface %d)\n",
- intf->dev.bus_id, configuration,
+ dev_name(&intf->dev), configuration,
intf->cur_altsetting->desc.bInterfaceNumber);
ret = device_add(&intf->dev);
if (ret != 0) {
dev_err(&dev->dev, "device_add(%s) --> %d\n",
- intf->dev.bus_id, ret);
+ dev_name(&intf->dev), ret);
continue;
}
usb_create_sysfs_intf_files(intf);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 32577437583..84fcaa6a21e 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -308,7 +308,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
* by location for diagnostics, tools, driver model, etc. The
* string is a path along hub ports, from the root. Each device's
* dev->devpath will be stable until USB is re-cabled, and hubs
- * are often labeled with these port numbers. The bus_id isn't
+ * are often labeled with these port numbers. The name isn't
* as stable: bus->busnum changes easily from modprobe order,
* cardbus or pci hotplugging, and so on.
*/
@@ -316,7 +316,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
dev->devpath[0] = '0';
dev->dev.parent = bus->controller;
- sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum);
+ dev_set_name(&dev->dev, "usb%d", bus->busnum);
root_hub = 1;
} else {
/* match any labeling on the hubs; it's one-based */
@@ -328,8 +328,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
"%s.%d", parent->devpath, port1);
dev->dev.parent = &parent->dev;
- sprintf(&dev->dev.bus_id[0], "%d-%s",
- bus->busnum, dev->devpath);
+ dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
/* hub driver sets up TT records */
}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1a8bc21c335..d9a6e16dbf8 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -29,6 +29,8 @@ extern int usb_choose_configuration(struct usb_device *udev);
extern void usb_kick_khubd(struct usb_device *dev);
extern int usb_match_device(struct usb_device *dev,
const struct usb_device_id *id);
+extern void usb_forced_unbind_intf(struct usb_interface *intf);
+extern void usb_rebind_intf(struct usb_interface *intf);
extern int usb_hub_init(void);
extern void usb_hub_cleanup(void);
@@ -140,26 +142,11 @@ extern struct usb_driver usbfs_driver;
extern const struct file_operations usbfs_devices_fops;
extern const struct file_operations usbdev_file_operations;
extern void usbfs_conn_disc_event(void);
+extern void usb_fs_classdev_common_remove(struct usb_device *udev);
extern int usb_devio_init(void);
extern void usb_devio_cleanup(void);
-struct dev_state {
- struct list_head list; /* state list */
- struct usb_device *dev;
- struct file *file;
- spinlock_t lock; /* protects the async urb lists */
- struct list_head async_pending;
- struct list_head async_completed;
- wait_queue_head_t wait; /* wake up if a request completed */
- unsigned int discsignr;
- struct pid *disc_pid;
- uid_t disc_uid, disc_euid;
- void __user *disccontext;
- unsigned long ifclaimed;
- u32 secid;
-};
-
/* internal notify stuff */
extern void usb_notify_add_device(struct usb_device *udev);
extern void usb_notify_remove_device(struct usb_device *udev);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d6bab0d5f45..c6a8c6b1116 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -586,6 +586,20 @@ config USB_G_PRINTER
For more information, see Documentation/usb/gadget_printer.txt
which includes sample code for accessing the device file.
+config USB_CDC_COMPOSITE
+ tristate "CDC Composite Device (Ethernet and ACM)"
+ depends on NET
+ help
+ This driver provides two functions in one configuration:
+ a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+ This driver requires four bulk and two interrupt endpoints,
+ plus the ability to handle altsettings. Not all peripheral
+ controllers are that capable.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module.
+
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index e258afd25fa..fcb5cb9094d 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -22,18 +22,22 @@ obj-$(CONFIG_USB_M66592) += m66592-udc.o
#
# USB gadget drivers
#
-g_zero-objs := zero.o usbstring.o config.o epautoconf.o
-g_ether-objs := ether.o usbstring.o config.o epautoconf.o
-g_serial-objs := serial.o usbstring.o config.o epautoconf.o
+C_UTILS = composite.o usbstring.o config.o epautoconf.o
+
+g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
+g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
+g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o usbstring.o config.o \
epautoconf.o
g_printer-objs := printer.o usbstring.o config.o \
epautoconf.o
+g_cdc-objs := cdc2.o u_ether.o f_ecm.o \
+ u_serial.o f_acm.o $(C_UTILS)
ifeq ($(CONFIG_USB_ETH_RNDIS),y)
- g_ether-objs += rndis.o
+ g_ether-objs += f_rndis.o rndis.o
endif
obj-$(CONFIG_USB_ZERO) += g_zero.o
@@ -43,4 +47,5 @@ obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index f261d2a9a5f..1500e1b3c30 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3342,7 +3342,7 @@ static int udc_probe(struct udc *dev)
spin_lock_init(&dev->lock);
dev->gadget.ops = &udc_ops;
- strcpy(dev->gadget.dev.bus_id, "gadget");
+ dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.release = gadget_release;
dev->gadget.name = name;
dev->gadget.name = name;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index b6b2a0a5ba3..e2d8a5d86c4 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1687,6 +1687,19 @@ static int __init at91udc_probe(struct platform_device *pdev)
udc->board.pullup_active_low);
}
+ /* newer chips have more FIFO memory than rm9200 */
+ if (cpu_is_at91sam9260()) {
+ udc->ep[0].maxpacket = 64;
+ udc->ep[3].maxpacket = 64;
+ udc->ep[4].maxpacket = 512;
+ udc->ep[5].maxpacket = 512;
+ } else if (cpu_is_at91sam9261()) {
+ udc->ep[3].maxpacket = 64;
+ } else if (cpu_is_at91sam9263()) {
+ udc->ep[0].maxpacket = 64;
+ udc->ep[3].maxpacket = 64;
+ }
+
udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
if (!udc->udp_baseaddr) {
retval = -ENOMEM;
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
new file mode 100644
index 00000000000..d490d028950
--- /dev/null
+++ b/drivers/usb/gadget/cdc2.c
@@ -0,0 +1,246 @@
+/*
+ * cdc2.c -- CDC Composite driver, with ECM and ACM support
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+
+#include "u_ether.h"
+#include "u_serial.h"
+
+
+#define DRIVER_DESC "CDC Composite Gadget"
+#define DRIVER_VERSION "King Kamehameha Day 2008"
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
+ * Instead: allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only this composite CDC configuration.
+ */
+#define CDC_VENDOR_NUM 0x0525 /* NetChip */
+#define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_device_descriptor device_desc = {
+ .bLength = sizeof device_desc,
+ .bDescriptorType = USB_DT_DEVICE,
+
+ .bcdUSB = __constant_cpu_to_le16(0x0200),
+
+ .bDeviceClass = USB_CLASS_COMM,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+ /* .bMaxPacketSize0 = f(hardware) */
+
+ /* Vendor and product id can be overridden by module parameters. */
+ .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM),
+ .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM),
+ /* .bcdDevice = f(hardware) */
+ /* .iManufacturer = DYNAMIC */
+ /* .iProduct = DYNAMIC */
+ /* NO SERIAL NUMBER */
+ .bNumConfigurations = 1,
+};
+
+static struct usb_otg_descriptor otg_descriptor = {
+ .bLength = sizeof otg_descriptor,
+ .bDescriptorType = USB_DT_OTG,
+
+ /* REVISIT SRP-only hardware is possible, although
+ * it would not be called "OTG" ...
+ */
+ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+ (struct usb_descriptor_header *) &otg_descriptor,
+ NULL,
+};
+
+
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX 0
+#define STRING_PRODUCT_IDX 1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+ [STRING_MANUFACTURER_IDX].s = manufacturer,
+ [STRING_PRODUCT_IDX].s = DRIVER_DESC,
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_dev,
+};
+
+static struct usb_gadget_strings *dev_strings[] = {
+ &stringtab_dev,
+ NULL,
+};
+
+static u8 hostaddr[ETH_ALEN];
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * We _always_ have both CDC ECM and CDC ACM functions.
+ */
+static int __init cdc_do_config(struct usb_configuration *c)
+{
+ int status;
+
+ if (gadget_is_otg(c->cdev->gadget)) {
+ c->descriptors = otg_desc;
+ c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ }
+
+ status = ecm_bind_config(c, hostaddr);
+ if (status < 0)
+ return status;
+
+ status = acm_bind_config(c, 0);
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+static struct usb_configuration cdc_config_driver = {
+ .label = "CDC Composite (ECM + ACM)",
+ .bind = cdc_do_config,
+ .bConfigurationValue = 1,
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init cdc_bind(struct usb_composite_dev *cdev)
+{
+ int gcnum;
+ struct usb_gadget *gadget = cdev->gadget;
+ int status;
+
+ if (!can_support_ecm(cdev->gadget)) {
+ ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+ return -EINVAL;
+ }
+
+ /* set up network link layer */
+ status = gether_setup(cdev->gadget, hostaddr);
+ if (status < 0)
+ return status;
+
+ /* set up serial link layer */
+ status = gserial_setup(cdev->gadget, 1);
+ if (status < 0)
+ goto fail0;
+
+ gcnum = usb_gadget_controller_number(gadget);
+ if (gcnum >= 0)
+ device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
+ else {
+ /* We assume that can_support_ecm() tells the truth;
+ * but if the controller isn't recognized at all then
+ * that assumption is a bit more likely to be wrong.
+ */
+ WARN(cdev, "controller '%s' not recognized; trying %s\n",
+ gadget->name,
+ cdc_config_driver.label);
+ device_desc.bcdDevice =
+ __constant_cpu_to_le16(0x0300 | 0x0099);
+ }
+
+
+ /* Allocate string descriptor numbers ... note that string
+ * contents can be overridden by the composite_dev glue.
+ */
+
+ /* device descriptor strings: manufacturer, product */
+ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+ init_utsname()->sysname, init_utsname()->release,
+ gadget->name);
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail1;
+ strings_dev[STRING_MANUFACTURER_IDX].id = status;
+ device_desc.iManufacturer = status;
+
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail1;
+ strings_dev[STRING_PRODUCT_IDX].id = status;
+ device_desc.iProduct = status;
+
+ /* register our configuration */
+ status = usb_add_config(cdev, &cdc_config_driver);
+ if (status < 0)
+ goto fail1;
+
+ INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+
+ return 0;
+
+fail1:
+ gserial_cleanup();
+fail0:
+ gether_cleanup();
+ return status;
+}
+
+static int __exit cdc_unbind(struct usb_composite_dev *cdev)
+{
+ gserial_cleanup();
+ gether_cleanup();
+ return 0;
+}
+
+static struct usb_composite_driver cdc_driver = {
+ .name = "g_cdc",
+ .dev = &device_desc,
+ .strings = dev_strings,
+ .bind = cdc_bind,
+ .unbind = __exit_p(cdc_unbind),
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
+static int __init init(void)
+{
+ return usb_composite_register(&cdc_driver);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+ usb_composite_unregister(&cdc_driver);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
new file mode 100644
index 00000000000..85c876c1f15
--- /dev/null
+++ b/drivers/usb/gadget/composite.c
@@ -0,0 +1,1041 @@
+/*
+ * composite.c - infrastructure for Composite USB Gadgets
+ *
+ * Copyright (C) 2006-2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <linux/usb/composite.h>
+
+
+/*
+ * The code in this file is utility code, used to build a gadget driver
+ * from one or more "function" drivers, one or more "configuration"
+ * objects, and a "usb_composite_driver" by gluing them together along
+ * with the relevant device-wide data.
+ */
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 512
+
+static struct usb_composite_driver *composite;
+
+/* Some systems will need runtime overrides for the product identifers
+ * published in the device descriptor, either numbers or strings or both.
+ * String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, 0);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, 0);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, 0);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, 0);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, 0);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, 0);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_add_function() - add a function to a configuration
+ * @config: the configuration
+ * @function: the function being added
+ * Context: single threaded during gadget setup
+ *
+ * After initialization, each configuration must have one or more
+ * functions added to it. Adding a function involves calling its @bind()
+ * method to allocate resources such as interface and string identifiers
+ * and endpoints.
+ *
+ * This function returns the value of the function's bind(), which is
+ * zero for success else a negative errno value.
+ */
+int __init usb_add_function(struct usb_configuration *config,
+ struct usb_function *function)
+{
+ int value = -EINVAL;
+
+ DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
+ function->name, function,
+ config->label, config);
+
+ if (!function->set_alt || !function->disable)
+ goto done;
+
+ function->config = config;
+ list_add_tail(&function->list, &config->functions);
+
+ /* REVISIT *require* function->bind? */
+ if (function->bind) {
+ value = function->bind(config, function);
+ if (value < 0) {
+ list_del(&function->list);
+ function->config = NULL;
+ }
+ } else
+ value = 0;
+
+ /* We allow configurations that don't work at both speeds.
+ * If we run into a lowspeed Linux system, treat it the same
+ * as full speed ... it's the function drivers that will need
+ * to avoid bulk and ISO transfers.
+ */
+ if (!config->fullspeed && function->descriptors)
+ config->fullspeed = true;
+ if (!config->highspeed && function->hs_descriptors)
+ config->highspeed = true;
+
+done:
+ if (value)
+ DBG(config->cdev, "adding '%s'/%p --> %d\n",
+ function->name, function, value);
+ return value;
+}
+
+/**
+ * usb_interface_id() - allocate an unused interface ID
+ * @config: configuration associated with the interface
+ * @function: function handling the interface
+ * Context: single threaded during gadget setup
+ *
+ * usb_interface_id() is called from usb_function.bind() callbacks to
+ * allocate new interface IDs. The function driver will then store that
+ * ID in interface, association, CDC union, and other descriptors. It
+ * will also handle any control requests targetted at that interface,
+ * particularly changing its altsetting via set_alt(). There may
+ * also be class-specific or vendor-specific requests to handle.
+ *
+ * All interface identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier. Note that since interface
+ * identifers are configuration-specific, functions used in more than
+ * one configuration (or more than once in a given configuration) need
+ * multiple versions of the relevant descriptors.
+ *
+ * Returns the interface ID which was allocated; or -ENODEV if no
+ * more interface IDs can be allocated.
+ */
+int __init usb_interface_id(struct usb_configuration *config,
+ struct usb_function *function)
+{
+ unsigned id = config->next_interface_id;
+
+ if (id < MAX_CONFIG_INTERFACES) {
+ config->interface[id] = function;
+ config->next_interface_id = id + 1;
+ return id;
+ }
+ return -ENODEV;
+}
+
+static int config_buf(struct usb_configuration *config,
+ enum usb_device_speed speed, void *buf, u8 type)
+{
+ struct usb_config_descriptor *c = buf;
+ void *next = buf + USB_DT_CONFIG_SIZE;
+ int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
+ struct usb_function *f;
+ int status;
+
+ /* write the config descriptor */
+ c = buf;
+ c->bLength = USB_DT_CONFIG_SIZE;
+ c->bDescriptorType = type;
+ /* wTotalLength is written later */
+ c->bNumInterfaces = config->next_interface_id;
+ c->bConfigurationValue = config->bConfigurationValue;
+ c->iConfiguration = config->iConfiguration;
+ c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
+ c->bMaxPower = config->bMaxPower;
+
+ /* There may be e.g. OTG descriptors */
+ if (config->descriptors) {
+ status = usb_descriptor_fillbuf(next, len,
+ config->descriptors);
+ if (status < 0)
+ return status;
+ len -= status;
+ next += status;
+ }
+
+ /* add each function's descriptors */
+ list_for_each_entry(f, &config->functions, list) {
+ struct usb_descriptor_header **descriptors;
+
+ if (speed == USB_SPEED_HIGH)
+ descriptors = f->hs_descriptors;
+ else
+ descriptors = f->descriptors;
+ if (!descriptors)
+ continue;
+ status = usb_descriptor_fillbuf(next, len,
+ (const struct usb_descriptor_header **) descriptors);
+ if (status < 0)
+ return status;
+ len -= status;
+ next += status;
+ }
+
+ len = next - buf;
+ c->wTotalLength = cpu_to_le16(len);
+ return len;
+}
+
+static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
+{
+ struct usb_gadget *gadget = cdev->gadget;
+ struct usb_configuration *c;
+ u8 type = w_value >> 8;
+ enum usb_device_speed speed = USB_SPEED_UNKNOWN;
+
+ if (gadget_is_dualspeed(gadget)) {
+ int hs = 0;
+
+ if (gadget->speed == USB_SPEED_HIGH)
+ hs = 1;
+ if (type == USB_DT_OTHER_SPEED_CONFIG)
+ hs = !hs;
+ if (hs)
+ speed = USB_SPEED_HIGH;
+
+ }
+
+ /* This is a lookup by config *INDEX* */
+ w_value &= 0xff;
+ list_for_each_entry(c, &cdev->configs, list) {
+ /* ignore configs that won't work at this speed */
+ if (speed == USB_SPEED_HIGH) {
+ if (!c->highspeed)
+ continue;
+ } else {
+ if (!c->fullspeed)
+ continue;
+ }
+ if (w_value == 0)
+ return config_buf(c, speed, cdev->req->buf, type);
+ w_value--;
+ }
+ return -EINVAL;
+}
+
+static int count_configs(struct usb_composite_dev *cdev, unsigned type)
+{
+ struct usb_gadget *gadget = cdev->gadget;
+ struct usb_configuration *c;
+ unsigned count = 0;
+ int hs = 0;
+
+ if (gadget_is_dualspeed(gadget)) {
+ if (gadget->speed == USB_SPEED_HIGH)
+ hs = 1;
+ if (type == USB_DT_DEVICE_QUALIFIER)
+ hs = !hs;
+ }
+ list_for_each_entry(c, &cdev->configs, list) {
+ /* ignore configs that won't work at this speed */
+ if (hs) {
+ if (!c->highspeed)
+ continue;
+ } else {
+ if (!c->fullspeed)
+ continue;
+ }
+ count++;
+ }
+ return count;
+}
+
+static void device_qual(struct usb_composite_dev *cdev)
+{
+ struct usb_qualifier_descriptor *qual = cdev->req->buf;
+
+ qual->bLength = sizeof(*qual);
+ qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
+ /* POLICY: same bcdUSB and device type info at both speeds */
+ qual->bcdUSB = cdev->desc.bcdUSB;
+ qual->bDeviceClass = cdev->desc.bDeviceClass;
+ qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
+ qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
+ /* ASSUME same EP0 fifo size at both speeds */
+ qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0;
+ qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
+ qual->bRESERVED = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void reset_config(struct usb_composite_dev *cdev)
+{
+ struct usb_function *f;
+
+ DBG(cdev, "reset config\n");
+
+ list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->disable)
+ f->disable(f);
+ }
+ cdev->config = NULL;
+}
+
+static int set_config(struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *ctrl, unsigned number)
+{
+ struct usb_gadget *gadget = cdev->gadget;
+ struct usb_configuration *c = NULL;
+ int result = -EINVAL;
+ unsigned power = gadget_is_otg(gadget) ? 8 : 100;
+ int tmp;
+
+ if (cdev->config)
+ reset_config(cdev);
+
+ if (number) {
+ list_for_each_entry(c, &cdev->configs, list) {
+ if (c->bConfigurationValue == number) {
+ result = 0;
+ break;
+ }
+ }
+ if (result < 0)
+ goto done;
+ } else
+ result = 0;
+
+ INFO(cdev, "%s speed config #%d: %s\n",
+ ({ char *speed;
+ switch (gadget->speed) {
+ case USB_SPEED_LOW: speed = "low"; break;
+ case USB_SPEED_FULL: speed = "full"; break;
+ case USB_SPEED_HIGH: speed = "high"; break;
+ default: speed = "?"; break;
+ } ; speed; }), number, c ? c->label : "unconfigured");
+
+ if (!c)
+ goto done;
+
+ cdev->config = c;
+
+ /* Initialize all interfaces by setting them to altsetting zero. */
+ for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
+ struct usb_function *f = c->interface[tmp];
+
+ if (!f)
+ break;
+
+ result = f->set_alt(f, tmp, 0);
+ if (result < 0) {
+ DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
+ tmp, f->name, f, result);
+
+ reset_config(cdev);
+ goto done;
+ }
+ }
+
+ /* when we return, be sure our power usage is valid */
+ power = 2 * c->bMaxPower;
+done:
+ usb_gadget_vbus_draw(gadget, power);
+ return result;
+}
+
+/**
+ * usb_add_config() - add a configuration to a device.
+ * @cdev: wraps the USB gadget
+ * @config: the configuration, with bConfigurationValue assigned
+ * Context: single threaded during gadget setup
+ *
+ * One of the main tasks of a composite driver's bind() routine is to
+ * add each of the configurations it supports, using this routine.
+ *
+ * This function returns the value of the configuration's bind(), which
+ * is zero for success else a negative errno value. Binding configurations
+ * assigns global resources including string IDs, and per-configuration
+ * resources such as interface IDs and endpoints.
+ */
+int __init usb_add_config(struct usb_composite_dev *cdev,
+ struct usb_configuration *config)
+{
+ int status = -EINVAL;
+ struct usb_configuration *c;
+
+ DBG(cdev, "adding config #%u '%s'/%p\n",
+ config->bConfigurationValue,
+ config->label, config);
+
+ if (!config->bConfigurationValue || !config->bind)
+ goto done;
+
+ /* Prevent duplicate configuration identifiers */
+ list_for_each_entry(c, &cdev->configs, list) {
+ if (c->bConfigurationValue == config->bConfigurationValue) {
+ status = -EBUSY;
+ goto done;
+ }
+ }
+
+ config->cdev = cdev;
+ list_add_tail(&config->list, &cdev->configs);
+
+ INIT_LIST_HEAD(&config->functions);
+ config->next_interface_id = 0;
+
+ status = config->bind(config);
+ if (status < 0) {
+ list_del(&config->list);
+ config->cdev = NULL;
+ } else {
+ unsigned i;
+
+ DBG(cdev, "cfg %d/%p speeds:%s%s\n",
+ config->bConfigurationValue, config,
+ config->highspeed ? " high" : "",
+ config->fullspeed
+ ? (gadget_is_dualspeed(cdev->gadget)
+ ? " full"
+ : " full/low")
+ : "");
+
+ for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
+ struct usb_function *f = config->interface[i];
+
+ if (!f)
+ continue;
+ DBG(cdev, " interface %d = %s/%p\n",
+ i, f->name, f);
+ }
+ }
+
+ /* set_alt(), or next config->bind(), sets up
+ * ep->driver_data as needed.
+ */
+ usb_ep_autoconfig_reset(cdev->gadget);
+
+done:
+ if (status)
+ DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
+ config->bConfigurationValue, status);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* We support strings in multiple languages ... string descriptor zero
+ * says which languages are supported. The typical case will be that
+ * only one language (probably English) is used, with I18N handled on
+ * the host side.
+ */
+
+static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
+{
+ const struct usb_gadget_strings *s;
+ u16 language;
+ __le16 *tmp;
+
+ while (*sp) {
+ s = *sp;
+ language = cpu_to_le16(s->language);
+ for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
+ if (*tmp == language)
+ goto repeat;
+ }
+ *tmp++ = language;
+repeat:
+ sp++;
+ }
+}
+
+static int lookup_string(
+ struct usb_gadget_strings **sp,
+ void *buf,
+ u16 language,
+ int id
+)
+{
+ struct usb_gadget_strings *s;
+ int value;
+
+ while (*sp) {
+ s = *sp++;
+ if (s->language != language)
+ continue;
+ value = usb_gadget_get_string(s, id, buf);
+ if (value > 0)
+ return value;
+ }
+ return -EINVAL;
+}
+
+static int get_string(struct usb_composite_dev *cdev,
+ void *buf, u16 language, int id)
+{
+ struct usb_configuration *c;
+ struct usb_function *f;
+ int len;
+
+ /* Yes, not only is USB's I18N support probably more than most
+ * folk will ever care about ... also, it's all supported here.
+ * (Except for UTF8 support for Unicode's "Astral Planes".)
+ */
+
+ /* 0 == report all available language codes */
+ if (id == 0) {
+ struct usb_string_descriptor *s = buf;
+ struct usb_gadget_strings **sp;
+
+ memset(s, 0, 256);
+ s->bDescriptorType = USB_DT_STRING;
+
+ sp = composite->strings;
+ if (sp)
+ collect_langs(sp, s->wData);
+
+ list_for_each_entry(c, &cdev->configs, list) {
+ sp = c->strings;
+ if (sp)
+ collect_langs(sp, s->wData);
+
+ list_for_each_entry(f, &c->functions, list) {
+ sp = f->strings;
+ if (sp)
+ collect_langs(sp, s->wData);
+ }
+ }
+
+ for (len = 0; s->wData[len] && len <= 126; len++)
+ continue;
+ if (!len)
+ return -EINVAL;
+
+ s->bLength = 2 * (len + 1);
+ return s->bLength;
+ }
+
+ /* Otherwise, look up and return a specified string. String IDs
+ * are device-scoped, so we look up each string table we're told
+ * about. These lookups are infrequent; simpler-is-better here.
+ */
+ if (composite->strings) {
+ len = lookup_string(composite->strings, buf, language, id);
+ if (len > 0)
+ return len;
+ }
+ list_for_each_entry(c, &cdev->configs, list) {
+ if (c->strings) {
+ len = lookup_string(c->strings, buf, language, id);
+ if (len > 0)
+ return len;
+ }
+ list_for_each_entry(f, &c->functions, list) {
+ if (!f->strings)
+ continue;
+ len = lookup_string(f->strings, buf, language, id);
+ if (len > 0)
+ return len;
+ }
+ }
+ return -EINVAL;
+}
+
+/**
+ * usb_string_id() - allocate an unused string ID
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * Context: single threaded during gadget setup
+ *
+ * @usb_string_id() is called from bind() callbacks to allocate
+ * string IDs. Drivers for functions, configurations, or gadgets will
+ * then store that ID in the appropriate descriptors and string table.
+ *
+ * All string identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier.
+ */
+int __init usb_string_id(struct usb_composite_dev *cdev)
+{
+ if (cdev->next_string_id < 254) {
+ /* string id 0 is reserved */
+ cdev->next_string_id++;
+ return cdev->next_string_id;
+ }
+ return -ENODEV;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ if (req->status || req->actual != req->length)
+ DBG((struct usb_composite_dev *) ep->driver_data,
+ "setup complete --> %d, %d/%d\n",
+ req->status, req->actual, req->length);
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's
+ * not handled lower down, in hardware or the hardware driver(like
+ * device and endpoint feature flags, and their status). It's all
+ * housekeeping for the gadget function we're implementing. Most of
+ * the work is in config and function specific setup.
+ */
+static int
+composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+ struct usb_function *f = NULL;
+
+ /* partial re-init of the response message; the function or the
+ * gadget might need to intercept e.g. a control-OUT completion
+ * when we delegate to it.
+ */
+ req->zero = 0;
+ req->complete = composite_setup_complete;
+ req->length = USB_BUFSIZ;
+ gadget->ep0->driver_data = cdev;
+
+ switch (ctrl->bRequest) {
+
+ /* we handle all standard USB descriptors */
+ case USB_REQ_GET_DESCRIPTOR:
+ if (ctrl->bRequestType != USB_DIR_IN)
+ goto unknown;
+ switch (w_value >> 8) {
+
+ case USB_DT_DEVICE:
+ cdev->desc.bNumConfigurations =
+ count_configs(cdev, USB_DT_DEVICE);
+ value = min(w_length, (u16) sizeof cdev->desc);
+ memcpy(req->buf, &cdev->desc, value);
+ break;
+ case USB_DT_DEVICE_QUALIFIER:
+ if (!gadget_is_dualspeed(gadget))
+ break;
+ device_qual(cdev);
+ value = min_t(int, w_length,
+ sizeof(struct usb_qualifier_descriptor));
+ break;
+ case USB_DT_OTHER_SPEED_CONFIG:
+ if (!gadget_is_dualspeed(gadget))
+ break;
+ /* FALLTHROUGH */
+ case USB_DT_CONFIG:
+ value = config_desc(cdev, w_value);
+ if (value >= 0)
+ value = min(w_length, (u16) value);
+ break;
+ case USB_DT_STRING:
+ value = get_string(cdev, req->buf,
+ w_index, w_value & 0xff);
+ if (value >= 0)
+ value = min(w_length, (u16) value);
+ break;
+ }
+ break;
+
+ /* any number of configs can work */
+ case USB_REQ_SET_CONFIGURATION:
+ if (ctrl->bRequestType != 0)
+ goto unknown;
+ if (gadget_is_otg(gadget)) {
+ if (gadget->a_hnp_support)
+ DBG(cdev, "HNP available\n");
+ else if (gadget->a_alt_hnp_support)
+ DBG(cdev, "HNP on another port\n");
+ else
+ VDBG(cdev, "HNP inactive\n");
+ }
+ spin_lock(&cdev->lock);
+ value = set_config(cdev, ctrl, w_value);
+ spin_unlock(&cdev->lock);
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ if (ctrl->bRequestType != USB_DIR_IN)
+ goto unknown;
+ if (cdev->config)
+ *(u8 *)req->buf = cdev->config->bConfigurationValue;
+ else
+ *(u8 *)req->buf = 0;
+ value = min(w_length, (u16) 1);
+ break;
+
+ /* function drivers must handle get/set altsetting; if there's
+ * no get() method, we know only altsetting zero works.
+ */
+ case USB_REQ_SET_INTERFACE:
+ if (ctrl->bRequestType != USB_RECIP_INTERFACE)
+ goto unknown;
+ if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+ break;
+ f = cdev->config->interface[w_index];
+ if (!f)
+ break;
+ if (w_value && !f->get_alt)
+ break;
+ value = f->set_alt(f, w_index, w_value);
+ break;
+ case USB_REQ_GET_INTERFACE:
+ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
+ goto unknown;
+ if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+ break;
+ f = cdev->config->interface[w_index];
+ if (!f)
+ break;
+ /* lots of interfaces only need altsetting zero... */
+ value = f->get_alt ? f->get_alt(f, w_index) : 0;
+ if (value < 0)
+ break;
+ *((u8 *)req->buf) = value;
+ value = min(w_length, (u16) 1);
+ break;
+ default:
+unknown:
+ VDBG(cdev,
+ "non-core control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+
+ /* functions always handle their interfaces ... punt other
+ * recipients (endpoint, other, WUSB, ...) to the current
+ * configuration code.
+ *
+ * REVISIT it could make sense to let the composite device
+ * take such requests too, if that's ever needed: to work
+ * in config 0, etc.
+ */
+ if ((ctrl->bRequestType & USB_RECIP_MASK)
+ == USB_RECIP_INTERFACE) {
+ f = cdev->config->interface[w_index];
+ if (f && f->setup)
+ value = f->setup(f, ctrl);
+ else
+ f = NULL;
+ }
+ if (value < 0 && !f) {
+ struct usb_configuration *c;
+
+ c = cdev->config;
+ if (c && c->setup)
+ value = c->setup(c, ctrl);
+ }
+
+ goto done;
+ }
+
+ /* respond with data transfer before status phase? */
+ if (value >= 0) {
+ req->length = value;
+ req->zero = value < w_length;
+ value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0) {
+ DBG(cdev, "ep_queue --> %d\n", value);
+ req->status = 0;
+ composite_setup_complete(gadget->ep0, req);
+ }
+ }
+
+done:
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static void composite_disconnect(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ unsigned long flags;
+
+ /* REVISIT: should we have config and device level
+ * disconnect callbacks?
+ */
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (cdev->config)
+ reset_config(cdev);
+ spin_unlock_irqrestore(&cdev->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void /* __init_or_exit */
+composite_unbind(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+
+ /* composite_disconnect() must already have been called
+ * by the underlying peripheral controller driver!
+ * so there's no i/o concurrency that could affect the
+ * state protected by cdev->lock.
+ */
+ WARN_ON(cdev->config);
+
+ while (!list_empty(&cdev->configs)) {
+ struct usb_configuration *c;
+
+ c = list_first_entry(&cdev->configs,
+ struct usb_configuration, list);
+ while (!list_empty(&c->functions)) {
+ struct usb_function *f;
+
+ f = list_first_entry(&c->functions,
+ struct usb_function, list);
+ list_del(&f->list);
+ if (f->unbind) {
+ DBG(cdev, "unbind function '%s'/%p\n",
+ f->name, f);
+ f->unbind(c, f);
+ /* may free memory for "f" */
+ }
+ }
+ list_del(&c->list);
+ if (c->unbind) {
+ DBG(cdev, "unbind config '%s'/%p\n", c->label, c);
+ c->unbind(c);
+ /* may free memory for "c" */
+ }
+ }
+ if (composite->unbind)
+ composite->unbind(cdev);
+
+ if (cdev->req) {
+ kfree(cdev->req->buf);
+ usb_ep_free_request(gadget->ep0, cdev->req);
+ }
+ kfree(cdev);
+ set_gadget_data(gadget, NULL);
+ composite = NULL;
+}
+
+static void __init
+string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
+{
+ struct usb_string *str = tab->strings;
+
+ for (str = tab->strings; str->s; str++) {
+ if (str->id == id) {
+ str->s = s;
+ return;
+ }
+ }
+}
+
+static void __init
+string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
+{
+ while (*tab) {
+ string_override_one(*tab, id, s);
+ tab++;
+ }
+}
+
+static int __init composite_bind(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev;
+ int status = -ENOMEM;
+
+ cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
+ if (!cdev)
+ return status;
+
+ spin_lock_init(&cdev->lock);
+ cdev->gadget = gadget;
+ set_gadget_data(gadget, cdev);
+ INIT_LIST_HEAD(&cdev->configs);
+
+ /* preallocate control response and buffer */
+ cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+ if (!cdev->req)
+ goto fail;
+ cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
+ if (!cdev->req->buf)
+ goto fail;
+ cdev->req->complete = composite_setup_complete;
+ gadget->ep0->driver_data = cdev;
+
+ cdev->bufsiz = USB_BUFSIZ;
+ cdev->driver = composite;
+
+ usb_gadget_set_selfpowered(gadget);
+
+ /* interface and string IDs start at zero via kzalloc.
+ * we force endpoints to start unassigned; few controller
+ * drivers will zero ep->driver_data.
+ */
+ usb_ep_autoconfig_reset(cdev->gadget);
+
+ /* composite gadget needs to assign strings for whole device (like
+ * serial number), register function drivers, potentially update
+ * power state and consumption, etc
+ */
+ status = composite->bind(cdev);
+ if (status < 0)
+ goto fail;
+
+ cdev->desc = *composite->dev;
+ cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+ /* standardized runtime overrides for device ID data */
+ if (idVendor)
+ cdev->desc.idVendor = cpu_to_le16(idVendor);
+ if (idProduct)
+ cdev->desc.idProduct = cpu_to_le16(idProduct);
+ if (bcdDevice)
+ cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
+ /* strings can't be assigned before bind() allocates the
+ * releavnt identifiers
+ */
+ if (cdev->desc.iManufacturer && iManufacturer)
+ string_override(composite->strings,
+ cdev->desc.iManufacturer, iManufacturer);
+ if (cdev->desc.iProduct && iProduct)
+ string_override(composite->strings,
+ cdev->desc.iProduct, iProduct);
+ if (cdev->desc.iSerialNumber && iSerialNumber)
+ string_override(composite->strings,
+ cdev->desc.iSerialNumber, iSerialNumber);
+
+ INFO(cdev, "%s ready\n", composite->name);
+ return 0;
+
+fail:
+ composite_unbind(gadget);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+composite_suspend(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+ /* REVISIT: should we have config and device level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "suspend\n");
+ if (cdev->config) {
+ list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->suspend)
+ f->suspend(f);
+ }
+ }
+}
+
+static void
+composite_resume(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev = get_gadget_data(gadget);
+ struct usb_function *f;
+
+ /* REVISIT: should we have config and device level
+ * suspend/resume callbacks?
+ */
+ DBG(cdev, "resume\n");
+ if (cdev->config) {
+ list_for_each_entry(f, &cdev->config->functions, list) {
+ if (f->resume)
+ f->resume(f);
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver composite_driver = {
+ .speed = USB_SPEED_HIGH,
+
+ .bind = composite_bind,
+ .unbind = __exit_p(composite_unbind),
+
+ .setup = composite_setup,
+ .disconnect = composite_disconnect,
+
+ .suspend = composite_suspend,
+ .resume = composite_resume,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ },
+};
+
+/**
+ * usb_composite_register() - register a composite driver
+ * @driver: the driver to register
+ * Context: single threaded during gadget setup
+ *
+ * This function is used to register drivers using the composite driver
+ * framework. The return value is zero, or a negative errno value.
+ * Those values normally come from the driver's @bind method, which does
+ * all the work of setting up the driver to match the hardware.
+ *
+ * On successful return, the gadget is ready to respond to requests from
+ * the host, unless one of its components invokes usb_gadget_disconnect()
+ * while it was binding. That would usually be done in order to wait for
+ * some userspace participation.
+ */
+int __init usb_composite_register(struct usb_composite_driver *driver)
+{
+ if (!driver || !driver->dev || !driver->bind || composite)
+ return -EINVAL;
+
+ if (!driver->name)
+ driver->name = "composite";
+ composite_driver.function = (char *) driver->name;
+ composite_driver.driver.name = driver->name;
+ composite = driver;
+
+ return usb_gadget_register_driver(&composite_driver);
+}
+
+/**
+ * usb_composite_unregister() - unregister a composite driver
+ * @driver: the driver to unregister
+ *
+ * This function is used to unregister drivers using the composite
+ * driver framework.
+ */
+void __exit usb_composite_unregister(struct usb_composite_driver *driver)
+{
+ if (composite != driver)
+ return;
+ usb_gadget_unregister_driver(&composite_driver);
+}
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index a4e54b2743f..1ca1c326392 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -96,7 +96,7 @@ int usb_gadget_config_buf(
/* config descriptor first */
if (length < USB_DT_CONFIG_SIZE || !desc)
return -EINVAL;
- *cp = *config;
+ *cp = *config;
/* then interface/endpoint/class/vendor/... */
len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
@@ -115,3 +115,77 @@ int usb_gadget_config_buf(
return len;
}
+/**
+ * usb_copy_descriptors - copy a vector of USB descriptors
+ * @src: null-terminated vector to copy
+ * Context: initialization code, which may sleep
+ *
+ * This makes a copy of a vector of USB descriptors. Its primary use
+ * is to support usb_function objects which can have multiple copies,
+ * each needing different descriptors. Functions may have static
+ * tables of descriptors, which are used as templates and customized
+ * with identifiers (for interfaces, strings, endpoints, and more)
+ * as needed by a given function instance.
+ */
+struct usb_descriptor_header **__init
+usb_copy_descriptors(struct usb_descriptor_header **src)
+{
+ struct usb_descriptor_header **tmp;
+ unsigned bytes;
+ unsigned n_desc;
+ void *mem;
+ struct usb_descriptor_header **ret;
+
+ /* count descriptors and their sizes; then add vector size */
+ for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
+ bytes += (*tmp)->bLength;
+ bytes += (n_desc + 1) * sizeof(*tmp);
+
+ mem = kmalloc(bytes, GFP_KERNEL);
+ if (!mem)
+ return NULL;
+
+ /* fill in pointers starting at "tmp",
+ * to descriptors copied starting at "mem";
+ * and return "ret"
+ */
+ tmp = mem;
+ ret = mem;
+ mem += (n_desc + 1) * sizeof(*tmp);
+ while (*src) {
+ memcpy(mem, *src, (*src)->bLength);
+ *tmp = mem;
+ tmp++;
+ mem += (*src)->bLength;
+ src++;
+ }
+ *tmp = NULL;
+
+ return ret;
+}
+
+/**
+ * usb_find_endpoint - find a copy of an endpoint descriptor
+ * @src: original vector of descriptors
+ * @copy: copy of @src
+ * @ep: endpoint descriptor found in @src
+ *
+ * This returns the copy of the @match descriptor made for @copy. Its
+ * intended use is to help remembering the endpoint descriptor to use
+ * when enabling a given endpoint.
+ */
+struct usb_endpoint_descriptor *__init
+usb_find_endpoint(
+ struct usb_descriptor_header **src,
+ struct usb_descriptor_header **copy,
+ struct usb_endpoint_descriptor *match
+)
+{
+ while (*src) {
+ if (*src == (void *) match)
+ return (void *)*copy;
+ src++;
+ copy++;
+ }
+ return NULL;
+}
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 42036192a03..21d1406af9e 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -862,7 +862,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
/* maybe claim OTG support, though we won't complete HNP */
dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
- strcpy (dum->gadget.dev.bus_id, "gadget");
+ dev_set_name(&dum->gadget.dev, "gadget");
dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register (&dum->gadget.dev);
@@ -1865,7 +1865,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
- hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
if (!hcd)
return -ENOMEM;
the_controller = hcd_to_dummy (hcd);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 8bdad221fa9..9462e30192d 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -159,6 +159,7 @@ ep_matches (
/* MATCH!! */
/* report address */
+ desc->bEndpointAddress &= USB_DIR_IN;
if (isdigit (ep->name [2])) {
u8 num = simple_strtol (&ep->name [2], NULL, 10);
desc->bEndpointAddress |= num;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 4ce3950b997..d7aaaa29b1e 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1,8 +1,9 @@
/*
* ether.c -- Ethernet gadget driver, with CDC and non-CDC options
*
- * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2003-2005,2008 David Brownell
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
*
* 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
@@ -23,18 +24,9 @@
#include <linux/kernel.h>
#include <linux/utsname.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
+#include "u_ether.h"
-#include "gadget_chips.h"
-
-/*-------------------------------------------------------------------------*/
/*
* Ethernet gadget driver -- with CDC and non-CDC options
@@ -46,7 +38,11 @@
* this USB-IF standard as its open-systems interoperability solution;
* most host side USB stacks (except from Microsoft) support it.
*
- * There's some hardware that can't talk CDC. We make that hardware
+ * This is sometimes called "CDC ECM" (Ethernet Control Model) to support
+ * TLA-soup. "CDC ACM" (Abstract Control Model) is for modems, and a new
+ * "CDC EEM" (Ethernet Emulation Model) is starting to spread.
+ *
+ * There's some hardware that can't talk CDC ECM. We make that hardware
* implement a "minimalist" vendor-agnostic CDC core: same framing, but
* link-level setup only requires activating the configuration. Only the
* endpoint descriptors, and product/vendor IDs, are relevant; no control
@@ -64,70 +60,40 @@
* A third option is also in use. Rather than CDC Ethernet, or something
* simpler, Microsoft pushes their own approach: RNDIS. The published
* RNDIS specs are ambiguous and appear to be incomplete, and are also
- * needlessly complex.
+ * needlessly complex. They borrow more from CDC ACM than CDC ECM.
*/
#define DRIVER_DESC "Ethernet Gadget"
-#define DRIVER_VERSION "May Day 2005"
-
-static const char shortname [] = "ether";
-static const char driver_desc [] = DRIVER_DESC;
-
-#define RX_EXTRA 20 /* guard against rx overflows */
-
-#include "rndis.h"
+#define DRIVER_VERSION "Memorial Day 2008"
-#ifndef CONFIG_USB_ETH_RNDIS
-#define rndis_uninit(x) do{}while(0)
-#define rndis_deregister(c) do{}while(0)
-#define rndis_exit() do{}while(0)
+#ifdef CONFIG_USB_ETH_RNDIS
+#define PREFIX "RNDIS/"
+#else
+#define PREFIX ""
#endif
-/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
-#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
- |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- |USB_CDC_PACKET_TYPE_PROMISCUOUS \
- |USB_CDC_PACKET_TYPE_DIRECTED)
-
-
-/*-------------------------------------------------------------------------*/
-
-struct eth_dev {
- spinlock_t lock;
- struct usb_gadget *gadget;
- struct usb_request *req; /* for control responses */
- struct usb_request *stat_req; /* for cdc & rndis status */
-
- u8 config;
- struct usb_ep *in_ep, *out_ep, *status_ep;
- const struct usb_endpoint_descriptor
- *in, *out, *status;
-
- spinlock_t req_lock;
- struct list_head tx_reqs, rx_reqs;
-
- struct net_device *net;
- struct net_device_stats stats;
- atomic_t tx_qlen;
-
- struct work_struct work;
- unsigned zlp:1;
- unsigned cdc:1;
- unsigned rndis:1;
- unsigned suspended:1;
- u16 cdc_filter;
- unsigned long todo;
-#define WORK_RX_MEMORY 0
- int rndis_config;
- u8 host_mac [ETH_ALEN];
-};
-
-/* This version autoconfigures as much as possible at run-time.
+/*
+ * This driver aims for interoperability by using CDC ECM unless
+ *
+ * can_support_ecm()
+ *
+ * returns false, in which case it supports the CDC Subset. By default,
+ * that returns true; most hardware has no problems with CDC ECM, that's
+ * a good default. Previous versions of this driver had no default; this
+ * version changes that, removing overhead for new controller support.
*
- * It also ASSUMES a self-powered device, without remote wakeup,
- * although remote wakeup support would make sense.
+ * IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE!
*/
+static inline bool has_rndis(void)
+{
+#ifdef CONFIG_USB_ETH_RNDIS
+ return true;
+#else
+ return false;
+#endif
+}
+
/*-------------------------------------------------------------------------*/
/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
@@ -137,8 +103,8 @@ struct eth_dev {
/* Thanks to NetChip Technologies for donating this product ID.
* It's for devices with only CDC Ethernet configurations.
*/
-#define CDC_VENDOR_NUM 0x0525 /* NetChip */
-#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
+#define CDC_VENDOR_NUM 0x0525 /* NetChip */
+#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
/* For hardware that can't talk CDC, we use the same vendor ID that
* ARM Linux has used for ethernet-over-usb, both with sa1100 and
@@ -162,274 +128,9 @@ struct eth_dev {
#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
-
-/* Some systems will want different product identifers published in the
- * device descriptor, either numbers or strings or both. These string
- * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
- */
-
-static ushort idVendor;
-module_param(idVendor, ushort, S_IRUGO);
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-
-static ushort idProduct;
-module_param(idProduct, ushort, S_IRUGO);
-MODULE_PARM_DESC(idProduct, "USB Product ID");
-
-static ushort bcdDevice;
-module_param(bcdDevice, ushort, S_IRUGO);
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-
-static char *iManufacturer;
-module_param(iManufacturer, charp, S_IRUGO);
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-
-static char *iProduct;
-module_param(iProduct, charp, S_IRUGO);
-MODULE_PARM_DESC(iProduct, "USB Product string");
-
-static char *iSerialNumber;
-module_param(iSerialNumber, charp, S_IRUGO);
-MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
-
-/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *dev_addr;
-module_param(dev_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
-
-/* this address is invisible to ifconfig */
-static char *host_addr;
-module_param(host_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Include CDC support if we could run on CDC-capable hardware. */
-
-#ifdef CONFIG_USB_GADGET_NET2280
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_DUMMY_HCD
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_GOKU
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_LH7A40X
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MQ11XX
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_OMAP
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_N9604
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_S3C2410
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AT91
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSBHSFC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define DEV_CONFIG_CDC
-#endif
-
-/* For CDC-incapable hardware, choose the simple cdc subset.
- * Anything that talks bulk (without notable bugs) can do this.
- */
-#ifdef CONFIG_USB_GADGET_PXA25X
-#define DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_PXA27X
-#define DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SUPERH
-#define DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SA1100
-/* use non-CDC for backwards compatibility */
-#define DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_M66592
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define DEV_CONFIG_CDC
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/* "main" config is either CDC, or its simple subset */
-static inline int is_cdc(struct eth_dev *dev)
-{
-#if !defined(DEV_CONFIG_SUBSET)
- return 1; /* only cdc possible */
-#elif !defined (DEV_CONFIG_CDC)
- return 0; /* only subset possible */
-#else
- return dev->cdc; /* depends on what hardware we found */
-#endif
-}
-
-/* "secondary" RNDIS config may sometimes be activated */
-static inline int rndis_active(struct eth_dev *dev)
-{
-#ifdef CONFIG_USB_ETH_RNDIS
- return dev->rndis;
-#else
- return 0;
-#endif
-}
-
-#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev))
-#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev))
-
-
-
-#define DEFAULT_QLEN 2 /* double buffering by default */
-
-/* peak bulk transfer bits-per-second */
-#define HS_BPS (13 * 512 * 8 * 1000 * 8)
-#define FS_BPS (19 * 64 * 1 * 1000 * 8)
-
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-#define DEVSPEED USB_SPEED_HIGH
-
-static unsigned qmult = 5;
-module_param (qmult, uint, S_IRUGO|S_IWUSR);
-
-
-/* for dual-speed hardware, use deeper queues at highspeed */
-#define qlen(gadget) \
- (DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
-
-static inline int BITRATE(struct usb_gadget *g)
-{
- return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;
-}
-
-#else /* full speed (low speed doesn't do bulk) */
-
-#define qmult 1
-
-#define DEVSPEED USB_SPEED_FULL
-
-#define qlen(gadget) DEFAULT_QLEN
-
-static inline int BITRATE(struct usb_gadget *g)
-{
- return FS_BPS;
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(d,level,fmt,args...) \
- printk(level "%s: " fmt , (d)->net->name , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
- xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
- do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VDEBUG DEBUG
-#else
-#define VDEBUG(dev,fmt,args...) \
- do { } while (0)
-#endif /* DEBUG */
-
-#define ERROR(dev,fmt,args...) \
- xprintk(dev , KERN_ERR , fmt , ## args)
-#define WARN(dev,fmt,args...) \
- xprintk(dev , KERN_WARNING , fmt , ## args)
-#define INFO(dev,fmt,args...) \
- xprintk(dev , KERN_INFO , fmt , ## args)
-
/*-------------------------------------------------------------------------*/
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation: descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand. For now we do either full CDC, or
- * our simple subset, with RNDIS as an optional second configuration.
- *
- * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet. But
- * the class descriptors match a modem (they're ignored; it's really just
- * Ethernet functionality), they don't need the NOP altsetting, and the
- * status transfer endpoint isn't optional.
- */
-
-#define STRING_MANUFACTURER 1
-#define STRING_PRODUCT 2
-#define STRING_ETHADDR 3
-#define STRING_DATA 4
-#define STRING_CONTROL 5
-#define STRING_RNDIS_CONTROL 6
-#define STRING_CDC 7
-#define STRING_SUBSET 8
-#define STRING_RNDIS 9
-#define STRING_SERIALNUMBER 10
-
-/* holds our biggest descriptor (or RNDIS response) */
-#define USB_BUFSIZ 256
-
-/*
- * This device advertises one configuration, eth_config, unless RNDIS
- * is enabled (rndis_config) on hardware supporting at least two configs.
- *
- * NOTE: Controllers like superh_udc should probably be able to use
- * an RNDIS-only configuration.
- *
- * FIXME define some higher-powered configurations to make it easier
- * to recharge batteries ...
- */
-
-#define DEV_CONFIG_VALUE 1 /* cdc or subset */
-#define DEV_RNDIS_CONFIG_VALUE 2 /* rndis; optional */
-
-static struct usb_device_descriptor
-device_desc = {
+static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
@@ -438,2220 +139,234 @@ device_desc = {
.bDeviceClass = USB_CLASS_COMM,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
+ /* .bMaxPacketSize0 = f(hardware) */
+ /* Vendor and product id defaults change according to what configs
+ * we support. (As does bNumConfigurations.) These values can
+ * also be overridden by module parameters.
+ */
.idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM),
- .iManufacturer = STRING_MANUFACTURER,
- .iProduct = STRING_PRODUCT,
+ /* .bcdDevice = f(hardware) */
+ /* .iManufacturer = DYNAMIC */
+ /* .iProduct = DYNAMIC */
+ /* NO SERIAL NUMBER */
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor
-otg_descriptor = {
+static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-static struct usb_config_descriptor
-eth_config = {
- .bLength = sizeof eth_config,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* compute wTotalLength on the fly */
- .bNumInterfaces = 2,
- .bConfigurationValue = DEV_CONFIG_VALUE,
- .iConfiguration = STRING_CDC,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 50,
-};
-
-#ifdef CONFIG_USB_ETH_RNDIS
-static struct usb_config_descriptor
-rndis_config = {
- .bLength = sizeof rndis_config,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* compute wTotalLength on the fly */
- .bNumInterfaces = 2,
- .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE,
- .iConfiguration = STRING_RNDIS,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 50,
-};
-#endif
-
-/*
- * Compared to the simple CDC subset, the full CDC Ethernet model adds
- * three class descriptors, two interface descriptors, optional status
- * endpoint. Both have a "data" interface and two bulk endpoints.
- * There are also differences in how control requests are handled.
- *
- * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the
- * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it
- * may hang or oops. Since bugfixes (or accurate specs, letting Linux
- * work around those bugs) are unlikely to ever come from MSFT, you may
- * wish to avoid using RNDIS.
- *
- * MCCI offers an alternative to RNDIS if you need to connect to Windows
- * but have hardware that can't support CDC Ethernet. We add descriptors
- * to present the CDC Subset as a (nonconformant) CDC MDLM variant called
- * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can
- * get those drivers from MCCI, or bundled with various products.
- */
-
-#ifdef DEV_CONFIG_CDC
-static struct usb_interface_descriptor
-control_intf = {
- .bLength = sizeof control_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 0,
- /* status endpoint is optional; this may be patched later */
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
- .bInterfaceProtocol = USB_CDC_PROTO_NONE,
- .iInterface = STRING_CONTROL,
-};
-#endif
-
-#ifdef CONFIG_USB_ETH_RNDIS
-static const struct usb_interface_descriptor
-rndis_control_intf = {
- .bLength = sizeof rndis_control_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 0,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
- .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
- .iInterface = STRING_RNDIS_CONTROL,
-};
-#endif
-
-static const struct usb_cdc_header_desc header_desc = {
- .bLength = sizeof header_desc,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_HEADER_TYPE,
-
- .bcdCDC = __constant_cpu_to_le16 (0x0110),
-};
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-static const struct usb_cdc_union_desc union_desc = {
- .bLength = sizeof union_desc,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_UNION_TYPE,
-
- .bMasterInterface0 = 0, /* index of control interface */
- .bSlaveInterface0 = 1, /* index of DATA interface */
-};
-
-#endif /* CDC || RNDIS */
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
- .bLength = sizeof call_mgmt_descriptor,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
-
- .bmCapabilities = 0x00,
- .bDataInterface = 0x01,
-};
-
-static const struct usb_cdc_acm_descriptor acm_descriptor = {
- .bLength = sizeof acm_descriptor,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_ACM_TYPE,
-
- .bmCapabilities = 0x00,
-};
-
-#endif
-
-#ifndef DEV_CONFIG_CDC
-
-/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
- * ways: data endpoints live in the control interface, there's no data
- * interface, and it's not used to talk to a cell phone radio.
- */
-
-static const struct usb_cdc_mdlm_desc mdlm_desc = {
- .bLength = sizeof mdlm_desc,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_MDLM_TYPE,
-
- .bcdVersion = __constant_cpu_to_le16(0x0100),
- .bGUID = {
- 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
- 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
- },
-};
-
-/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
- * can't really use its struct. All we do here is say that we're using
- * the submode of "SAFE" which directly matches the CDC Subset.
- */
-static const u8 mdlm_detail_desc[] = {
- 6,
- USB_DT_CS_INTERFACE,
- USB_CDC_MDLM_DETAIL_TYPE,
-
- 0, /* "SAFE" */
- 0, /* network control capabilities (none) */
- 0, /* network data capabilities ("raw" encapsulation) */
-};
-
-#endif
-
-static const struct usb_cdc_ether_desc ether_desc = {
- .bLength = sizeof ether_desc,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
-
- /* this descriptor actually adds value, surprise! */
- .iMACAddress = STRING_ETHADDR,
- .bmEthernetStatistics = __constant_cpu_to_le32 (0), /* no statistics */
- .wMaxSegmentSize = __constant_cpu_to_le16 (ETH_FRAME_LEN),
- .wNumberMCFilters = __constant_cpu_to_le16 (0),
- .bNumberPowerFilters = 0,
-};
-
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-/* include the status endpoint if we can, even where it's optional.
- * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
- * packet, to simplify cancellation; and a big transfer interval, to
- * waste less bandwidth.
- *
- * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
- * if they ignore the connect/disconnect notifications that real aether
- * can provide. more advanced cdc configurations might want to support
- * encapsulated commands (vendor-specific, using control-OUT).
- *
- * RNDIS requires the status endpoint, since it uses that encapsulation
- * mechanism for its funky RPC scheme.
- */
-
-#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
-
-static struct usb_endpoint_descriptor
-fs_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT),
- .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
-};
-#endif
-
-#ifdef DEV_CONFIG_CDC
-
-/* the default data interface has no endpoints ... */
-
-static const struct usb_interface_descriptor
-data_nop_intf = {
- .bLength = sizeof data_nop_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 1,
- .bAlternateSetting = 0,
- .bNumEndpoints = 0,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
-};
-
-/* ... but the "real" data interface has two bulk endpoints */
-
-static const struct usb_interface_descriptor
-data_intf = {
- .bLength = sizeof data_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 1,
- .bAlternateSetting = 1,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = STRING_DATA,
-};
-
-#endif
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-/* RNDIS doesn't activate by changing to the "real" altsetting */
-
-static const struct usb_interface_descriptor
-rndis_data_intf = {
- .bLength = sizeof rndis_data_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 1,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = STRING_DATA,
-};
-
-#endif
-
-#ifdef DEV_CONFIG_SUBSET
-
-/*
- * "Simple" CDC-subset option is a simple vendor-neutral model that most
- * full speed controllers can handle: one interface, two bulk endpoints.
- *
- * To assist host side drivers, we fancy it up a bit, and add descriptors
- * so some host side drivers will understand it as a "SAFE" variant.
- */
-
-static const struct usb_interface_descriptor
-subset_data_intf = {
- .bLength = sizeof subset_data_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM,
- .bInterfaceProtocol = 0,
- .iInterface = STRING_DATA,
-};
-
-#endif /* SUBSET */
-
-
-static struct usb_endpoint_descriptor
-fs_source_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor
-fs_sink_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ /* REVISIT SRP-only hardware is possible, although
+ * it would not be called "OTG" ...
+ */
+ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
-static const struct usb_descriptor_header *fs_eth_function [11] = {
+static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
- /* "cdc" mode descriptors */
- (struct usb_descriptor_header *) &control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &ether_desc,
- /* NOTE: status endpoint may need to be removed */
- (struct usb_descriptor_header *) &fs_status_desc,
- /* data interface, with altsetting */
- (struct usb_descriptor_header *) &data_nop_intf,
- (struct usb_descriptor_header *) &data_intf,
- (struct usb_descriptor_header *) &fs_source_desc,
- (struct usb_descriptor_header *) &fs_sink_desc,
NULL,
-#endif /* DEV_CONFIG_CDC */
};
-static inline void __init fs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
- /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
- fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
- fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
- fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
- fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
- fs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
- fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc;
- fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc;
- fs_eth_function[8] = NULL;
-#else
- fs_eth_function[1] = NULL;
-#endif
-}
-#ifdef CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *fs_rndis_function [] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- /* control interface matches ACM, not Ethernet */
- (struct usb_descriptor_header *) &rndis_control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &fs_status_desc,
- /* data interface has no altsetting */
- (struct usb_descriptor_header *) &rndis_data_intf,
- (struct usb_descriptor_header *) &fs_source_desc,
- (struct usb_descriptor_header *) &fs_sink_desc,
- NULL,
-};
-#endif
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-static struct usb_endpoint_descriptor
-hs_status_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16 (STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
-};
-#endif /* DEV_CONFIG_CDC */
-
-static struct usb_endpoint_descriptor
-hs_source_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16 (512),
-};
-
-static struct usb_endpoint_descriptor
-hs_sink_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16 (512),
-};
+/* string IDs are assigned dynamically */
-static struct usb_qualifier_descriptor
-dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+#define STRING_MANUFACTURER_IDX 0
+#define STRING_PRODUCT_IDX 1
- .bcdUSB = __constant_cpu_to_le16 (0x0200),
- .bDeviceClass = USB_CLASS_COMM,
+static char manufacturer[50];
- .bNumConfigurations = 1,
+static struct usb_string strings_dev[] = {
+ [STRING_MANUFACTURER_IDX].s = manufacturer,
+ [STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC,
+ { } /* end of list */
};
-static const struct usb_descriptor_header *hs_eth_function [11] = {
- (struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
- /* "cdc" mode descriptors */
- (struct usb_descriptor_header *) &control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &ether_desc,
- /* NOTE: status endpoint may need to be removed */
- (struct usb_descriptor_header *) &hs_status_desc,
- /* data interface, with altsetting */
- (struct usb_descriptor_header *) &data_nop_intf,
- (struct usb_descriptor_header *) &data_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- NULL,
-#endif /* DEV_CONFIG_CDC */
+static struct usb_gadget_strings stringtab_dev = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_dev,
};
-static inline void __init hs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
- /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
- hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
- hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
- hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
- hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
- hs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
- hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc;
- hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc;
- hs_eth_function[8] = NULL;
-#else
- hs_eth_function[1] = NULL;
-#endif
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *hs_rndis_function [] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- /* control interface matches ACM, not Ethernet */
- (struct usb_descriptor_header *) &rndis_control_intf,
- (struct usb_descriptor_header *) &header_desc,
- (struct usb_descriptor_header *) &call_mgmt_descriptor,
- (struct usb_descriptor_header *) &acm_descriptor,
- (struct usb_descriptor_header *) &union_desc,
- (struct usb_descriptor_header *) &hs_status_desc,
- /* data interface has no altsetting */
- (struct usb_descriptor_header *) &rndis_data_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
+static struct usb_gadget_strings *dev_strings[] = {
+ &stringtab_dev,
NULL,
};
-#endif
-
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
- struct usb_endpoint_descriptor *fs)
-{
- if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
- return hs;
- return fs;
-}
+static u8 hostaddr[ETH_ALEN];
/*-------------------------------------------------------------------------*/
-/* descriptors that are built on-demand */
-
-static char manufacturer [50];
-static char product_desc [40] = DRIVER_DESC;
-static char serial_number [20];
-
-/* address that the host will use ... usually assigned at random */
-static char ethaddr [2 * ETH_ALEN + 1];
-
-/* static strings, in UTF-8 */
-static struct usb_string strings [] = {
- { STRING_MANUFACTURER, manufacturer, },
- { STRING_PRODUCT, product_desc, },
- { STRING_SERIALNUMBER, serial_number, },
- { STRING_DATA, "Ethernet Data", },
- { STRING_ETHADDR, ethaddr, },
-#ifdef DEV_CONFIG_CDC
- { STRING_CDC, "CDC Ethernet", },
- { STRING_CONTROL, "CDC Communications Control", },
-#endif
-#ifdef DEV_CONFIG_SUBSET
- { STRING_SUBSET, "CDC Ethernet Subset", },
-#endif
-#ifdef CONFIG_USB_ETH_RNDIS
- { STRING_RNDIS, "RNDIS", },
- { STRING_RNDIS_CONTROL, "RNDIS Communications Control", },
-#endif
- { } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab = {
- .language = 0x0409, /* en-us */
- .strings = strings,
-};
-
/*
- * one config, two interfaces: control, data.
- * complications: class descriptors, and an altsetting.
- */
-static int
-config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg)
-{
- int len;
- const struct usb_config_descriptor *config;
- const struct usb_descriptor_header **function;
- int hs = 0;
-
- if (gadget_is_dualspeed(g)) {
- hs = (g->speed == USB_SPEED_HIGH);
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- hs = !hs;
- }
-#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function)
-
- if (index >= device_desc.bNumConfigurations)
- return -EINVAL;
-
-#ifdef CONFIG_USB_ETH_RNDIS
- /* list the RNDIS config first, to make Microsoft's drivers
- * happy. DOCSIS 1.0 needs this too.
- */
- if (device_desc.bNumConfigurations == 2 && index == 0) {
- config = &rndis_config;
- function = which_fn (rndis);
- } else
-#endif
- {
- config = &eth_config;
- function = which_fn (eth);
- }
-
- /* for now, don't advertise srp-only devices */
- if (!is_otg)
- function++;
-
- len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function);
- if (len < 0)
- return len;
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
-
-static int
-set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
-{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- /* status endpoint used for RNDIS and (optionally) CDC */
- if (!subset_active(dev) && dev->status_ep) {
- dev->status = ep_desc (gadget, &hs_status_desc,
- &fs_status_desc);
- dev->status_ep->driver_data = dev;
-
- result = usb_ep_enable (dev->status_ep, dev->status);
- if (result != 0) {
- DEBUG (dev, "enable %s --> %d\n",
- dev->status_ep->name, result);
- goto done;
- }
- }
-#endif
-
- dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
- dev->in_ep->driver_data = dev;
-
- dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
- dev->out_ep->driver_data = dev;
-
- /* With CDC, the host isn't allowed to use these two data
- * endpoints in the default altsetting for the interface.
- * so we don't activate them yet. Reset from SET_INTERFACE.
- *
- * Strictly speaking RNDIS should work the same: activation is
- * a side effect of setting a packet filter. Deactivation is
- * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
- */
- if (!cdc_active(dev)) {
- result = usb_ep_enable (dev->in_ep, dev->in);
- if (result != 0) {
- DEBUG(dev, "enable %s --> %d\n",
- dev->in_ep->name, result);
- goto done;
- }
-
- result = usb_ep_enable (dev->out_ep, dev->out);
- if (result != 0) {
- DEBUG (dev, "enable %s --> %d\n",
- dev->out_ep->name, result);
- goto done;
- }
- }
-
-done:
- if (result == 0)
- result = alloc_requests (dev, qlen (gadget), gfp_flags);
-
- /* on error, disable any endpoints */
- if (result < 0) {
- if (!subset_active(dev) && dev->status_ep)
- (void) usb_ep_disable (dev->status_ep);
- dev->status = NULL;
- (void) usb_ep_disable (dev->in_ep);
- (void) usb_ep_disable (dev->out_ep);
- dev->in = NULL;
- dev->out = NULL;
- }
-
- /* activate non-CDC configs right away
- * this isn't strictly according to the RNDIS spec
- */
- else if (!cdc_active (dev)) {
- netif_carrier_on (dev->net);
- if (netif_running (dev->net)) {
- spin_unlock (&dev->lock);
- eth_start (dev, GFP_ATOMIC);
- spin_lock (&dev->lock);
- }
- }
-
- if (result == 0)
- DEBUG (dev, "qlen %d\n", qlen (gadget));
-
- /* caller is responsible for cleanup on error */
- return result;
-}
-
-static void eth_reset_config (struct eth_dev *dev)
-{
- struct usb_request *req;
-
- if (dev->config == 0)
- return;
-
- DEBUG (dev, "%s\n", __func__);
-
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
- rndis_uninit(dev->rndis_config);
-
- /* disable endpoints, forcing (synchronous) completion of
- * pending i/o. then free the requests.
- */
- if (dev->in) {
- usb_ep_disable (dev->in_ep);
- spin_lock(&dev->req_lock);
- while (likely (!list_empty (&dev->tx_reqs))) {
- req = container_of (dev->tx_reqs.next,
- struct usb_request, list);
- list_del (&req->list);
-
- spin_unlock(&dev->req_lock);
- usb_ep_free_request (dev->in_ep, req);
- spin_lock(&dev->req_lock);
- }
- spin_unlock(&dev->req_lock);
- }
- if (dev->out) {
- usb_ep_disable (dev->out_ep);
- spin_lock(&dev->req_lock);
- while (likely (!list_empty (&dev->rx_reqs))) {
- req = container_of (dev->rx_reqs.next,
- struct usb_request, list);
- list_del (&req->list);
-
- spin_unlock(&dev->req_lock);
- usb_ep_free_request (dev->out_ep, req);
- spin_lock(&dev->req_lock);
- }
- spin_unlock(&dev->req_lock);
- }
-
- if (dev->status) {
- usb_ep_disable (dev->status_ep);
- }
- dev->rndis = 0;
- dev->cdc_filter = 0;
- dev->config = 0;
-}
-
-/* change our operational config. must agree with the code
- * that returns config descriptors, and altsetting code.
+ * We may not have an RNDIS configuration, but if we do it needs to be
+ * the first one present. That's to make Microsoft's drivers happy,
+ * and to follow DOCSIS 1.0 (cable modem standard).
*/
-static int
-eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
+static int __init rndis_do_config(struct usb_configuration *c)
{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
- if (gadget_is_sa1100 (gadget)
- && dev->config
- && atomic_read (&dev->tx_qlen) != 0) {
- /* tx fifo is full, but we can't clear it...*/
- INFO (dev, "can't change configurations\n");
- return -ESPIPE;
- }
- eth_reset_config (dev);
-
- switch (number) {
- case DEV_CONFIG_VALUE:
- result = set_ether_config (dev, gfp_flags);
- break;
-#ifdef CONFIG_USB_ETH_RNDIS
- case DEV_RNDIS_CONFIG_VALUE:
- dev->rndis = 1;
- result = set_ether_config (dev, gfp_flags);
- break;
-#endif
- default:
- result = -EINVAL;
- /* FALL THROUGH */
- case 0:
- break;
- }
-
- if (result) {
- if (number)
- eth_reset_config (dev);
- usb_gadget_vbus_draw(dev->gadget,
- gadget_is_otg(dev->gadget) ? 8 : 100);
- } else {
- char *speed;
- unsigned power;
-
- power = 2 * eth_config.bMaxPower;
- usb_gadget_vbus_draw(dev->gadget, power);
+ /* FIXME alloc iConfiguration string, set it in c->strings */
- switch (gadget->speed) {
- case USB_SPEED_FULL: speed = "full"; break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- case USB_SPEED_HIGH: speed = "high"; break;
-#endif
- default: speed = "?"; break;
- }
-
- dev->config = number;
- INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",
- speed, number, power, driver_desc,
- rndis_active(dev)
- ? "RNDIS"
- : (cdc_active(dev)
- ? "CDC Ethernet"
- : "CDC Ethernet Subset"));
+ if (gadget_is_otg(c->cdev->gadget)) {
+ c->descriptors = otg_desc;
+ c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEV_CONFIG_CDC
-/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
- * only to notify the host about link status changes (which we support) or
- * report completion of some encapsulated command (as used in RNDIS). Since
- * we want this CDC Ethernet code to be vendor-neutral, we don't use that
- * command mechanism; and only one status request is ever queued.
- */
-
-static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct usb_cdc_notification *event = req->buf;
- int value = req->status;
- struct eth_dev *dev = ep->driver_data;
-
- /* issue the second notification if host reads the first */
- if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
- && value == 0) {
- __le32 *data = req->buf + sizeof *event;
-
- event->bmRequestType = 0xA1;
- event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
- event->wValue = __constant_cpu_to_le16 (0);
- event->wIndex = __constant_cpu_to_le16 (1);
- event->wLength = __constant_cpu_to_le16 (8);
-
- /* SPEED_CHANGE data is up/down speeds in bits/sec */
- data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
-
- req->length = STATUS_BYTECOUNT;
- value = usb_ep_queue (ep, req, GFP_ATOMIC);
- DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
- if (value == 0)
- return;
- } else if (value != -ECONNRESET)
- DEBUG (dev, "event %02x --> %d\n",
- event->bNotificationType, value);
- req->context = NULL;
+ return rndis_bind_config(c, hostaddr);
}
-static void issue_start_status (struct eth_dev *dev)
-{
- struct usb_request *req = dev->stat_req;
- struct usb_cdc_notification *event;
- int value;
-
- DEBUG (dev, "%s, flush old status first\n", __func__);
-
- /* flush old status
- *
- * FIXME ugly idiom, maybe we'd be better with just
- * a "cancel the whole queue" primitive since any
- * unlink-one primitive has way too many error modes.
- * here, we "know" toggle is already clear...
- *
- * FIXME iff req->context != null just dequeue it
- */
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
-
- /* 3.8.1 says to issue first NETWORK_CONNECTION, then
- * a SPEED_CHANGE. could be useful in some configs.
- */
- event = req->buf;
- event->bmRequestType = 0xA1;
- event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
- event->wValue = __constant_cpu_to_le16 (1); /* connected */
- event->wIndex = __constant_cpu_to_le16 (1);
- event->wLength = 0;
-
- req->length = sizeof *event;
- req->complete = eth_status_complete;
- req->context = dev;
-
- value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
- if (value < 0)
- DEBUG (dev, "status buf queue --> %d\n", value);
-}
-
-#endif
+static struct usb_configuration rndis_config_driver = {
+ .label = "RNDIS",
+ .bind = rndis_do_config,
+ .bConfigurationValue = 2,
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
+};
/*-------------------------------------------------------------------------*/
-static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DEBUG ((struct eth_dev *) ep->driver_data,
- "setup complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DEBUG ((struct eth_dev *) ep->driver_data,
- "rndis response complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-
- /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
-}
-
-static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct eth_dev *dev = ep->driver_data;
- int status;
-
- /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
- spin_lock(&dev->lock);
- status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
- if (status < 0)
- ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
- spin_unlock(&dev->lock);
-}
-
-#endif /* RNDIS */
-
/*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down. CDC has a number of less-common features:
- *
- * - two interfaces: control, and ethernet data
- * - Ethernet data interface has two altsettings: default, and active
- * - class-specific descriptors for the control interface
- * - class-specific control requests
+ * We _always_ have an ECM or CDC Subset configuration.
*/
-static int
-eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+static int __init eth_do_config(struct usb_configuration *c)
{
- struct eth_dev *dev = get_gadget_data (gadget);
- struct usb_request *req = dev->req;
- int value = -EOPNOTSUPP;
- u16 wIndex = le16_to_cpu(ctrl->wIndex);
- u16 wValue = le16_to_cpu(ctrl->wValue);
- u16 wLength = le16_to_cpu(ctrl->wLength);
-
- /* descriptors just go into the pre-allocated ep0 buffer,
- * while config change events may enable network traffic.
- */
- req->complete = eth_setup_complete;
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- switch (wValue >> 8) {
-
- case USB_DT_DEVICE:
- value = min (wLength, (u16) sizeof device_desc);
- memcpy (req->buf, &device_desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
- break;
- value = min (wLength, (u16) sizeof dev_qualifier);
- memcpy (req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
- break;
- // FALLTHROUGH
- case USB_DT_CONFIG:
- value = config_buf(gadget, req->buf,
- wValue >> 8,
- wValue & 0xff,
- gadget_is_otg(gadget));
- if (value >= 0)
- value = min (wLength, (u16) value);
- break;
-
- case USB_DT_STRING:
- value = usb_gadget_get_string (&stringtab,
- wValue & 0xff, req->buf);
- if (value >= 0)
- value = min (wLength, (u16) value);
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- break;
- if (gadget->a_hnp_support)
- DEBUG (dev, "HNP available\n");
- else if (gadget->a_alt_hnp_support)
- DEBUG (dev, "HNP needs a different root port\n");
- spin_lock (&dev->lock);
- value = eth_set_config (dev, wValue, GFP_ATOMIC);
- spin_unlock (&dev->lock);
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- *(u8 *)req->buf = dev->config;
- value = min (wLength, (u16) 1);
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE
- || !dev->config
- || wIndex > 1)
- break;
- if (!cdc_active(dev) && wIndex != 0)
- break;
- spin_lock (&dev->lock);
-
- /* PXA hardware partially handles SET_INTERFACE;
- * we need to kluge around that interference.
- */
- if (gadget_is_pxa (gadget)) {
- value = eth_set_config (dev, DEV_CONFIG_VALUE,
- GFP_ATOMIC);
- goto done_set_intf;
- }
-
-#ifdef DEV_CONFIG_CDC
- switch (wIndex) {
- case 0: /* control/master intf */
- if (wValue != 0)
- break;
- if (dev->status) {
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
- }
- value = 0;
- break;
- case 1: /* data intf */
- if (wValue > 1)
- break;
- usb_ep_disable (dev->in_ep);
- usb_ep_disable (dev->out_ep);
-
- /* CDC requires the data transfers not be done from
- * the default interface setting ... also, setting
- * the non-default interface resets filters etc.
- */
- if (wValue == 1) {
- if (!cdc_active (dev))
- break;
- usb_ep_enable (dev->in_ep, dev->in);
- usb_ep_enable (dev->out_ep, dev->out);
- dev->cdc_filter = DEFAULT_FILTER;
- netif_carrier_on (dev->net);
- if (dev->status)
- issue_start_status (dev);
- if (netif_running (dev->net)) {
- spin_unlock (&dev->lock);
- eth_start (dev, GFP_ATOMIC);
- spin_lock (&dev->lock);
- }
- } else {
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
- }
- value = 0;
- break;
- }
-#else
- /* FIXME this is wrong, as is the assumption that
- * all non-PXA hardware talks real CDC ...
- */
- dev_warn (&gadget->dev, "set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
-
-done_set_intf:
- spin_unlock (&dev->lock);
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
- || !dev->config
- || wIndex > 1)
- break;
- if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0)
- break;
-
- /* for CDC, iff carrier is on, data interface is active. */
- if (rndis_active(dev) || wIndex != 1)
- *(u8 *)req->buf = 0;
- else
- *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
- value = min (wLength, (u16) 1);
- break;
-
-#ifdef DEV_CONFIG_CDC
- case USB_CDC_SET_ETHERNET_PACKET_FILTER:
- /* see 6.2.30: no data, wIndex = interface,
- * wValue = packet filter bitmap
- */
- if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- || !cdc_active(dev)
- || wLength != 0
- || wIndex > 1)
- break;
- DEBUG (dev, "packet filter %02x\n", wValue);
- dev->cdc_filter = wValue;
- value = 0;
- break;
-
- /* and potentially:
- * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
- * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
- * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
- * case USB_CDC_GET_ETHERNET_STATISTIC:
- */
-
-#endif /* DEV_CONFIG_CDC */
+ /* FIXME alloc iConfiguration string, set it in c->strings */
-#ifdef CONFIG_USB_ETH_RNDIS
- /* RNDIS uses the CDC command encapsulation mechanism to implement
- * an RPC scheme, with much getting/setting of attributes by OID.
- */
- case USB_CDC_SEND_ENCAPSULATED_COMMAND:
- if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- || !rndis_active(dev)
- || wLength > USB_BUFSIZ
- || wValue
- || rndis_control_intf.bInterfaceNumber
- != wIndex)
- break;
- /* read the request, then process it */
- value = wLength;
- req->complete = rndis_command_complete;
- /* later, rndis_control_ack () sends a notification */
- break;
-
- case USB_CDC_GET_ENCAPSULATED_RESPONSE:
- if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
- == ctrl->bRequestType
- && rndis_active(dev)
- // && wLength >= 0x0400
- && !wValue
- && rndis_control_intf.bInterfaceNumber
- == wIndex) {
- u8 *buf;
- u32 n;
-
- /* return the result */
- buf = rndis_get_next_response(dev->rndis_config, &n);
- if (buf) {
- memcpy(req->buf, buf, n);
- req->complete = rndis_response_complete;
- rndis_free_response(dev->rndis_config, buf);
- value = n;
- }
- /* else stalls ... spec says to avoid that */
- }
- break;
-#endif /* RNDIS */
-
- default:
- VDEBUG (dev,
- "unknown control req%02x.%02x v%04x i%04x l%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- wValue, wIndex, wLength);
+ if (gadget_is_otg(c->cdev->gadget)) {
+ c->descriptors = otg_desc;
+ c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- /* respond with data transfer before status phase? */
- if (value >= 0) {
- req->length = value;
- req->zero = value < wLength
- && (value % gadget->ep0->maxpacket) == 0;
- value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DEBUG (dev, "ep_queue --> %d\n", value);
- req->status = 0;
- eth_setup_complete (gadget->ep0, req);
- }
- }
-
- /* host either stalls (value < 0) or reports success */
- return value;
-}
-
-static void
-eth_disconnect (struct usb_gadget *gadget)
-{
- struct eth_dev *dev = get_gadget_data (gadget);
- unsigned long flags;
-
- spin_lock_irqsave (&dev->lock, flags);
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
- eth_reset_config (dev);
- spin_unlock_irqrestore (&dev->lock, flags);
-
- /* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
-
- /* next we may get setup() calls to enumerate new connections;
- * or an unbind() during shutdown (including removing module).
- */
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int eth_change_mtu (struct net_device *net, int new_mtu)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- if (dev->rndis)
- return -EBUSY;
-
- if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
- return -ERANGE;
- /* no zero-length packet read wanted after mtu-sized packets */
- if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
- return -EDOM;
- net->mtu = new_mtu;
- return 0;
-}
-
-static struct net_device_stats *eth_get_stats (struct net_device *net)
-{
- return &((struct eth_dev *)netdev_priv(net))->stats;
-}
-
-static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
-{
- struct eth_dev *dev = netdev_priv(net);
- strlcpy(p->driver, shortname, sizeof p->driver);
- strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
- strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
- strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info);
-}
-
-static u32 eth_get_link(struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
-static struct ethtool_ops ops = {
- .get_drvinfo = eth_get_drvinfo,
- .get_link = eth_get_link
-};
-
-static void defer_kevent (struct eth_dev *dev, int flag)
-{
- if (test_and_set_bit (flag, &dev->todo))
- return;
- if (!schedule_work (&dev->work))
- ERROR (dev, "kevent %d may have been dropped\n", flag);
+ if (can_support_ecm(c->cdev->gadget))
+ return ecm_bind_config(c, hostaddr);
else
- DEBUG (dev, "kevent %d scheduled\n", flag);
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req);
-
-static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
-{
- struct sk_buff *skb;
- int retval = -ENOMEM;
- size_t size;
-
- /* Padding up to RX_EXTRA handles minor disagreements with host.
- * Normally we use the USB "terminate on short read" convention;
- * so allow up to (N*maxpacket), since that memory is normally
- * already allocated. Some hardware doesn't deal well with short
- * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
- * byte off the end (to force hardware errors on overflow).
- *
- * RNDIS uses internal framing, and explicitly allows senders to
- * pad to end-of-packet. That's potentially nice for speed,
- * but means receivers can't recover synch on their own.
- */
- size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
- size += dev->out_ep->maxpacket - 1;
- if (rndis_active(dev))
- size += sizeof (struct rndis_packet_msg_type);
- size -= size % dev->out_ep->maxpacket;
-
- skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
- if (skb == NULL) {
- DEBUG (dev, "no rx skb\n");
- goto enomem;
- }
-
- /* Some platforms perform better when IP packets are aligned,
- * but on at least one, checksumming fails otherwise. Note:
- * RNDIS headers involve variable numbers of LE32 values.
- */
- skb_reserve(skb, NET_IP_ALIGN);
-
- req->buf = skb->data;
- req->length = size;
- req->complete = rx_complete;
- req->context = skb;
-
- retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
- if (retval == -ENOMEM)
-enomem:
- defer_kevent (dev, WORK_RX_MEMORY);
- if (retval) {
- DEBUG (dev, "rx submit --> %d\n", retval);
- if (skb)
- dev_kfree_skb_any(skb);
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->rx_reqs);
- spin_unlock(&dev->req_lock);
- }
- return retval;
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct sk_buff *skb = req->context;
- struct eth_dev *dev = ep->driver_data;
- int status = req->status;
-
- switch (status) {
-
- /* normal completion */
- case 0:
- skb_put (skb, req->actual);
- /* we know MaxPacketsPerTransfer == 1 here */
- if (rndis_active(dev))
- status = rndis_rm_hdr (skb);
- if (status < 0
- || ETH_HLEN > skb->len
- || skb->len > ETH_FRAME_LEN) {
- dev->stats.rx_errors++;
- dev->stats.rx_length_errors++;
- DEBUG (dev, "rx length %d\n", skb->len);
- break;
- }
-
- skb->protocol = eth_type_trans (skb, dev->net);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
-
- /* no buffer copies needed, unless hardware can't
- * use skb buffers.
- */
- status = netif_rx (skb);
- skb = NULL;
- break;
-
- /* software-driven interface shutdown */
- case -ECONNRESET: // unlink
- case -ESHUTDOWN: // disconnect etc
- VDEBUG (dev, "rx shutdown, code %d\n", status);
- goto quiesce;
-
- /* for hardware automagic (such as pxa) */
- case -ECONNABORTED: // endpoint reset
- DEBUG (dev, "rx %s reset\n", ep->name);
- defer_kevent (dev, WORK_RX_MEMORY);
-quiesce:
- dev_kfree_skb_any (skb);
- goto clean;
-
- /* data overrun */
- case -EOVERFLOW:
- dev->stats.rx_over_errors++;
- // FALLTHROUGH
-
- default:
- dev->stats.rx_errors++;
- DEBUG (dev, "rx status %d\n", status);
- break;
- }
-
- if (skb)
- dev_kfree_skb_any (skb);
- if (!netif_running (dev->net)) {
-clean:
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->rx_reqs);
- spin_unlock(&dev->req_lock);
- req = NULL;
- }
- if (req)
- rx_submit (dev, req, GFP_ATOMIC);
-}
-
-static int prealloc (struct list_head *list, struct usb_ep *ep,
- unsigned n, gfp_t gfp_flags)
-{
- unsigned i;
- struct usb_request *req;
-
- if (!n)
- return -ENOMEM;
-
- /* queue/recycle up to N requests */
- i = n;
- list_for_each_entry (req, list, list) {
- if (i-- == 0)
- goto extra;
- }
- while (i--) {
- req = usb_ep_alloc_request (ep, gfp_flags);
- if (!req)
- return list_empty (list) ? -ENOMEM : 0;
- list_add (&req->list, list);
- }
- return 0;
-
-extra:
- /* free extras */
- for (;;) {
- struct list_head *next;
-
- next = req->list.next;
- list_del (&req->list);
- usb_ep_free_request (ep, req);
-
- if (next == list)
- break;
-
- req = container_of (next, struct usb_request, list);
- }
- return 0;
-}
-
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
-{
- int status;
-
- spin_lock(&dev->req_lock);
- status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
- if (status < 0)
- goto fail;
- status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
- if (status < 0)
- goto fail;
- goto done;
-fail:
- DEBUG (dev, "can't alloc requests\n");
-done:
- spin_unlock(&dev->req_lock);
- return status;
-}
-
-static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
-{
- struct usb_request *req;
- unsigned long flags;
-
- /* fill unused rxq slots with some skb */
- spin_lock_irqsave(&dev->req_lock, flags);
- while (!list_empty (&dev->rx_reqs)) {
- req = container_of (dev->rx_reqs.next,
- struct usb_request, list);
- list_del_init (&req->list);
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- if (rx_submit (dev, req, gfp_flags) < 0) {
- defer_kevent (dev, WORK_RX_MEMORY);
- return;
- }
-
- spin_lock_irqsave(&dev->req_lock, flags);
- }
- spin_unlock_irqrestore(&dev->req_lock, flags);
-}
-
-static void eth_work (struct work_struct *work)
-{
- struct eth_dev *dev = container_of(work, struct eth_dev, work);
-
- if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
- if (netif_running (dev->net))
- rx_fill (dev, GFP_KERNEL);
- }
-
- if (dev->todo)
- DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct sk_buff *skb = req->context;
- struct eth_dev *dev = ep->driver_data;
-
- switch (req->status) {
- default:
- dev->stats.tx_errors++;
- VDEBUG (dev, "tx err %d\n", req->status);
- /* FALLTHROUGH */
- case -ECONNRESET: // unlink
- case -ESHUTDOWN: // disconnect etc
- break;
- case 0:
- dev->stats.tx_bytes += skb->len;
- }
- dev->stats.tx_packets++;
-
- spin_lock(&dev->req_lock);
- list_add (&req->list, &dev->tx_reqs);
- spin_unlock(&dev->req_lock);
- dev_kfree_skb_any (skb);
-
- atomic_dec (&dev->tx_qlen);
- if (netif_carrier_ok (dev->net))
- netif_wake_queue (dev->net);
-}
-
-static inline int eth_is_promisc (struct eth_dev *dev)
-{
- /* no filters for the CDC subset; always promisc */
- if (subset_active (dev))
- return 1;
- return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
-}
-
-static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- int length = skb->len;
- int retval;
- struct usb_request *req = NULL;
- unsigned long flags;
-
- /* apply outgoing CDC or RNDIS filters */
- if (!eth_is_promisc (dev)) {
- u8 *dest = skb->data;
-
- if (is_multicast_ether_addr(dest)) {
- u16 type;
-
- /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
- * SET_ETHERNET_MULTICAST_FILTERS requests
- */
- if (is_broadcast_ether_addr(dest))
- type = USB_CDC_PACKET_TYPE_BROADCAST;
- else
- type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
- if (!(dev->cdc_filter & type)) {
- dev_kfree_skb_any (skb);
- return 0;
- }
- }
- /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
- }
-
- spin_lock_irqsave(&dev->req_lock, flags);
- /*
- * this freelist can be empty if an interrupt triggered disconnect()
- * and reconfigured the gadget (shutting down this queue) after the
- * network stack decided to xmit but before we got the spinlock.
- */
- if (list_empty(&dev->tx_reqs)) {
- spin_unlock_irqrestore(&dev->req_lock, flags);
- return 1;
- }
-
- req = container_of (dev->tx_reqs.next, struct usb_request, list);
- list_del (&req->list);
-
- /* temporarily stop TX queue when the freelist empties */
- if (list_empty (&dev->tx_reqs))
- netif_stop_queue (net);
- spin_unlock_irqrestore(&dev->req_lock, flags);
-
- /* no buffer copies needed, unless the network stack did it
- * or the hardware can't use skb buffers.
- * or there's not enough space for any RNDIS headers we need
- */
- if (rndis_active(dev)) {
- struct sk_buff *skb_rndis;
-
- skb_rndis = skb_realloc_headroom (skb,
- sizeof (struct rndis_packet_msg_type));
- if (!skb_rndis)
- goto drop;
-
- dev_kfree_skb_any (skb);
- skb = skb_rndis;
- rndis_add_hdr (skb);
- length = skb->len;
- }
- req->buf = skb->data;
- req->context = skb;
- req->complete = tx_complete;
-
- /* use zlp framing on tx for strict CDC-Ether conformance,
- * though any robust network rx path ignores extra padding.
- * and some hardware doesn't like to write zlps.
- */
- req->zero = 1;
- if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
- length++;
-
- req->length = length;
-
- /* throttle highspeed IRQ rate back slightly */
- if (gadget_is_dualspeed(dev->gadget))
- req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
- ? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
- : 0;
-
- retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
- switch (retval) {
- default:
- DEBUG (dev, "tx queue err %d\n", retval);
- break;
- case 0:
- net->trans_start = jiffies;
- atomic_inc (&dev->tx_qlen);
- }
-
- if (retval) {
-drop:
- dev->stats.tx_dropped++;
- dev_kfree_skb_any (skb);
- spin_lock_irqsave(&dev->req_lock, flags);
- if (list_empty (&dev->tx_reqs))
- netif_start_queue (net);
- list_add (&req->list, &dev->tx_reqs);
- spin_unlock_irqrestore(&dev->req_lock, flags);
- }
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-/* The interrupt endpoint is used in RNDIS to notify the host when messages
- * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT
- * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even
- * REMOTE_NDIS_KEEPALIVE_MSG.
- *
- * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and
- * normally just one notification will be queued.
- */
-
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
-static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
-
-static void
-rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
-{
- struct eth_dev *dev = ep->driver_data;
-
- if (req->status || req->actual != req->length)
- DEBUG (dev,
- "rndis control ack complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
- req->context = NULL;
-
- if (req != dev->stat_req)
- eth_req_free(ep, req);
-}
-
-static int rndis_control_ack (struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- int length;
- struct usb_request *resp = dev->stat_req;
-
- /* in case RNDIS calls this after disconnect */
- if (!dev->status) {
- DEBUG (dev, "status ENODEV\n");
- return -ENODEV;
- }
-
- /* in case queue length > 1 */
- if (resp->context) {
- resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC);
- if (!resp)
- return -ENOMEM;
- }
-
- /* Send RNDIS RESPONSE_AVAILABLE notification;
- * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
- */
- resp->length = 8;
- resp->complete = rndis_control_ack_complete;
- resp->context = dev;
-
- *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
- *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
-
- length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
- if (length < 0) {
- resp->status = 0;
- rndis_control_ack_complete (dev->status_ep, resp);
- }
-
- return 0;
-}
-
-#else
-
-#define rndis_control_ack NULL
-
-#endif /* RNDIS */
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
-{
- DEBUG (dev, "%s\n", __func__);
-
- /* fill the rx queue */
- rx_fill (dev, gfp_flags);
-
- /* and open the tx floodgates */
- atomic_set (&dev->tx_qlen, 0);
- netif_wake_queue (dev->net);
- if (rndis_active(dev)) {
- rndis_set_param_medium (dev->rndis_config,
- NDIS_MEDIUM_802_3,
- BITRATE(dev->gadget)/100);
- (void) rndis_signal_connect (dev->rndis_config);
- }
-}
-
-static int eth_open (struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- DEBUG (dev, "%s\n", __func__);
- if (netif_carrier_ok (dev->net))
- eth_start (dev, GFP_KERNEL);
- return 0;
+ return geth_bind_config(c, hostaddr);
}
-static int eth_stop (struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
-
- VDEBUG (dev, "%s\n", __func__);
- netif_stop_queue (net);
-
- DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
- dev->stats.rx_packets, dev->stats.tx_packets,
- dev->stats.rx_errors, dev->stats.tx_errors
- );
-
- /* ensure there are no more active requests */
- if (dev->config) {
- usb_ep_disable (dev->in_ep);
- usb_ep_disable (dev->out_ep);
- if (netif_carrier_ok (dev->net)) {
- DEBUG (dev, "host still using in/out endpoints\n");
- // FIXME idiom may leave toggle wrong here
- usb_ep_enable (dev->in_ep, dev->in);
- usb_ep_enable (dev->out_ep, dev->out);
- }
- if (dev->status_ep) {
- usb_ep_disable (dev->status_ep);
- usb_ep_enable (dev->status_ep, dev->status);
- }
- }
-
- if (rndis_active(dev)) {
- rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
- (void) rndis_signal_disconnect (dev->rndis_config);
- }
-
- return 0;
-}
+static struct usb_configuration eth_config_driver = {
+ /* .label = f(hardware) */
+ .bind = eth_do_config,
+ .bConfigurationValue = 1,
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
+};
/*-------------------------------------------------------------------------*/
-static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
+static int __init eth_bind(struct usb_composite_dev *cdev)
{
- struct usb_request *req;
-
- req = usb_ep_alloc_request (ep, gfp_flags);
- if (!req)
- return NULL;
-
- req->buf = kmalloc (size, gfp_flags);
- if (!req->buf) {
- usb_ep_free_request (ep, req);
- req = NULL;
- }
- return req;
-}
-
-static void
-eth_req_free (struct usb_ep *ep, struct usb_request *req)
-{
- kfree (req->buf);
- usb_ep_free_request (ep, req);
-}
-
-
-static void /* __init_or_exit */
-eth_unbind (struct usb_gadget *gadget)
-{
- struct eth_dev *dev = get_gadget_data (gadget);
-
- DEBUG (dev, "unbind\n");
- rndis_deregister (dev->rndis_config);
- rndis_exit ();
-
- /* we've already been disconnected ... no i/o is active */
- if (dev->req) {
- eth_req_free (gadget->ep0, dev->req);
- dev->req = NULL;
- }
- if (dev->stat_req) {
- eth_req_free (dev->status_ep, dev->stat_req);
- dev->stat_req = NULL;
- }
-
- unregister_netdev (dev->net);
- free_netdev(dev->net);
-
- /* assuming we used keventd, it must quiesce too */
- flush_scheduled_work ();
- set_gadget_data (gadget, NULL);
-}
-
-static u8 __init nibble (unsigned char c)
-{
- if (likely (isdigit (c)))
- return c - '0';
- c = toupper (c);
- if (likely (isxdigit (c)))
- return 10 + c - 'A';
- return 0;
-}
+ int gcnum;
+ struct usb_gadget *gadget = cdev->gadget;
+ int status;
-static int __init get_ether_addr(const char *str, u8 *dev_addr)
-{
- if (str) {
- unsigned i;
+ /* set up network link layer */
+ status = gether_setup(cdev->gadget, hostaddr);
+ if (status < 0)
+ return status;
- for (i = 0; i < 6; i++) {
- unsigned char num;
+ /* set up main config label and device descriptor */
+ if (can_support_ecm(cdev->gadget)) {
+ /* ECM */
+ eth_config_driver.label = "CDC Ethernet (ECM)";
+ } else {
+ /* CDC Subset */
+ eth_config_driver.label = "CDC Subset/SAFE";
- if((*str == '.') || (*str == ':'))
- str++;
- num = nibble(*str++) << 4;
- num |= (nibble(*str++));
- dev_addr [i] = num;
- }
- if (is_valid_ether_addr (dev_addr))
- return 0;
+ device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
+ device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
+ device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
}
- random_ether_addr(dev_addr);
- return 1;
-}
-
-static int __init
-eth_bind (struct usb_gadget *gadget)
-{
- struct eth_dev *dev;
- struct net_device *net;
- u8 cdc = 1, zlp = 1, rndis = 1;
- struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
- int status = -ENOMEM;
- int gcnum;
-
- /* these flags are only ever cleared; compiler take note */
-#ifndef DEV_CONFIG_CDC
- cdc = 0;
-#endif
-#ifndef CONFIG_USB_ETH_RNDIS
- rndis = 0;
-#endif
- /* Because most host side USB stacks handle CDC Ethernet, that
- * standard protocol is _strongly_ preferred for interop purposes.
- * (By everyone except Microsoft.)
- */
- if (gadget_is_pxa (gadget)) {
- /* pxa doesn't support altsettings */
- cdc = 0;
- } else if (gadget_is_musbhdrc(gadget)) {
- /* reduce tx dma overhead by avoiding special cases */
- zlp = 0;
- } else if (gadget_is_sh(gadget)) {
- /* sh doesn't support multiple interfaces or configs */
- cdc = 0;
- rndis = 0;
- } else if (gadget_is_sa1100 (gadget)) {
- /* hardware can't write zlps */
- zlp = 0;
- /* sa1100 CAN do CDC, without status endpoint ... we use
- * non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
- */
- cdc = 0;
+ if (has_rndis()) {
+ /* RNDIS plus ECM-or-Subset */
+ device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
+ device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
+ device_desc.bNumConfigurations = 2;
}
- gcnum = usb_gadget_controller_number (gadget);
+ gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
- device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+ device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
else {
- /* can't assume CDC works. don't want to default to
- * anything less functional on CDC-capable hardware,
- * so we fail in this case.
+ /* We assume that can_support_ecm() tells the truth;
+ * but if the controller isn't recognized at all then
+ * that assumption is a bit more likely to be wrong.
*/
- dev_err (&gadget->dev,
- "controller '%s' not recognized\n",
- gadget->name);
- return -ENODEV;
- }
- snprintf (manufacturer, sizeof manufacturer, "%s %s/%s",
- init_utsname()->sysname, init_utsname()->release,
- gadget->name);
-
- /* If there's an RNDIS configuration, that's what Windows wants to
- * be using ... so use these product IDs here and in the "linux.inf"
- * needed to install MSFT drivers. Current Linux kernels will use
- * the second configuration if it's CDC Ethernet, and need some help
- * to choose the right configuration otherwise.
- */
- if (rndis) {
- device_desc.idVendor =
- __constant_cpu_to_le16(RNDIS_VENDOR_NUM);
- device_desc.idProduct =
- __constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
- snprintf (product_desc, sizeof product_desc,
- "RNDIS/%s", driver_desc);
-
- /* CDC subset ... recognized by Linux since 2.4.10, but Windows
- * drivers aren't widely available. (That may be improved by
- * supporting one submode of the "SAFE" variant of MDLM.)
- */
- } else if (!cdc) {
- device_desc.idVendor =
- __constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
- device_desc.idProduct =
- __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
- }
-
- /* support optional vendor/distro customization */
- if (idVendor) {
- if (!idProduct) {
- dev_err (&gadget->dev, "idVendor needs idProduct!\n");
- return -ENODEV;
- }
- device_desc.idVendor = cpu_to_le16(idVendor);
- device_desc.idProduct = cpu_to_le16(idProduct);
- if (bcdDevice)
- device_desc.bcdDevice = cpu_to_le16(bcdDevice);
- }
- if (iManufacturer)
- strlcpy (manufacturer, iManufacturer, sizeof manufacturer);
- if (iProduct)
- strlcpy (product_desc, iProduct, sizeof product_desc);
- if (iSerialNumber) {
- device_desc.iSerialNumber = STRING_SERIALNUMBER,
- strlcpy(serial_number, iSerialNumber, sizeof serial_number);
- }
-
- /* all we really need is bulk IN/OUT */
- usb_ep_autoconfig_reset (gadget);
- in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
- if (!in_ep) {
-autoconf_fail:
- dev_err (&gadget->dev,
- "can't autoconfigure on %s\n",
- gadget->name);
- return -ENODEV;
- }
- in_ep->driver_data = in_ep; /* claim */
-
- out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
- if (!out_ep)
- goto autoconf_fail;
- out_ep->driver_data = out_ep; /* claim */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- /* CDC Ethernet control interface doesn't require a status endpoint.
- * Since some hosts expect one, try to allocate one anyway.
- */
- if (cdc || rndis) {
- status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
- if (status_ep) {
- status_ep->driver_data = status_ep; /* claim */
- } else if (rndis) {
- dev_err (&gadget->dev,
- "can't run RNDIS on %s\n",
- gadget->name);
- return -ENODEV;
-#ifdef DEV_CONFIG_CDC
- /* pxa25x only does CDC subset; often used with RNDIS */
- } else if (cdc) {
- control_intf.bNumEndpoints = 0;
- /* FIXME remove endpoint from descriptor list */
-#endif
- }
- }
-#endif
-
- /* one config: cdc, else minimal subset */
- if (!cdc) {
- eth_config.bNumInterfaces = 1;
- eth_config.iConfiguration = STRING_SUBSET;
-
- /* use functions to set these up, in case we're built to work
- * with multiple controllers and must override CDC Ethernet.
- */
- fs_subset_descriptors();
- hs_subset_descriptors();
- }
-
- device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
- usb_gadget_set_selfpowered (gadget);
-
- /* For now RNDIS is always a second config */
- if (rndis)
- device_desc.bNumConfigurations = 2;
-
- if (gadget_is_dualspeed(gadget)) {
- if (rndis)
- dev_qualifier.bNumConfigurations = 2;
- else if (!cdc)
- dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
-
- /* assumes ep0 uses the same value for both speeds ... */
- dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
- /* and that all endpoints are dual-speed */
- hs_source_desc.bEndpointAddress =
- fs_source_desc.bEndpointAddress;
- hs_sink_desc.bEndpointAddress =
- fs_sink_desc.bEndpointAddress;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- if (status_ep)
- hs_status_desc.bEndpointAddress =
- fs_status_desc.bEndpointAddress;
-#endif
+ WARN(cdev, "controller '%s' not recognized; trying %s\n",
+ gadget->name,
+ eth_config_driver.label);
+ device_desc.bcdDevice =
+ __constant_cpu_to_le16(0x0300 | 0x0099);
}
- if (gadget_is_otg(gadget)) {
- otg_descriptor.bmAttributes |= USB_OTG_HNP,
- eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- eth_config.bMaxPower = 4;
-#ifdef CONFIG_USB_ETH_RNDIS
- rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- rndis_config.bMaxPower = 4;
-#endif
- }
-
- net = alloc_etherdev (sizeof *dev);
- if (!net)
- return status;
- dev = netdev_priv(net);
- spin_lock_init (&dev->lock);
- spin_lock_init (&dev->req_lock);
- INIT_WORK (&dev->work, eth_work);
- INIT_LIST_HEAD (&dev->tx_reqs);
- INIT_LIST_HEAD (&dev->rx_reqs);
-
- /* network device setup */
- dev->net = net;
- strcpy (net->name, "usb%d");
- dev->cdc = cdc;
- dev->zlp = zlp;
- dev->in_ep = in_ep;
- dev->out_ep = out_ep;
- dev->status_ep = status_ep;
-
- /* Module params for these addresses should come from ID proms.
- * The host side address is used with CDC and RNDIS, and commonly
- * ends up in a persistent config database. It's not clear if
- * host side code for the SAFE thing cares -- its original BLAN
- * thing didn't, Sharp never assigned those addresses on Zaurii.
+ /* Allocate string descriptor numbers ... note that string
+ * contents can be overridden by the composite_dev glue.
*/
- if (get_ether_addr(dev_addr, net->dev_addr))
- dev_warn(&gadget->dev,
- "using random %s ethernet address\n", "self");
- if (get_ether_addr(host_addr, dev->host_mac))
- dev_warn(&gadget->dev,
- "using random %s ethernet address\n", "host");
- snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
- dev->host_mac [0], dev->host_mac [1],
- dev->host_mac [2], dev->host_mac [3],
- dev->host_mac [4], dev->host_mac [5]);
-
- if (rndis) {
- status = rndis_init();
- if (status < 0) {
- dev_err (&gadget->dev, "can't init RNDIS, %d\n",
- status);
- goto fail;
- }
- }
- net->change_mtu = eth_change_mtu;
- net->get_stats = eth_get_stats;
- net->hard_start_xmit = eth_start_xmit;
- net->open = eth_open;
- net->stop = eth_stop;
- // watchdog_timeo, tx_timeout ...
- // set_multicast_list
- SET_ETHTOOL_OPS(net, &ops);
+ /* device descriptor strings: manufacturer, product */
+ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+ init_utsname()->sysname, init_utsname()->release,
+ gadget->name);
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail;
+ strings_dev[STRING_MANUFACTURER_IDX].id = status;
+ device_desc.iManufacturer = status;
- /* preallocate control message data and buffer */
- dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL);
- if (!dev->req)
+ status = usb_string_id(cdev);
+ if (status < 0)
goto fail;
- dev->req->complete = eth_setup_complete;
+ strings_dev[STRING_PRODUCT_IDX].id = status;
+ device_desc.iProduct = status;
- /* ... and maybe likewise for status transfer */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- if (dev->status_ep) {
- dev->stat_req = eth_req_alloc (dev->status_ep,
- STATUS_BYTECOUNT, GFP_KERNEL);
- if (!dev->stat_req) {
- eth_req_free (gadget->ep0, dev->req);
+ /* register our configuration(s); RNDIS first, if it's used */
+ if (has_rndis()) {
+ status = usb_add_config(cdev, &rndis_config_driver);
+ if (status < 0)
goto fail;
- }
- dev->stat_req->context = NULL;
}
-#endif
-
- /* finish hookup to lower layer ... */
- dev->gadget = gadget;
- set_gadget_data (gadget, dev);
- gadget->ep0->driver_data = dev;
- /* two kinds of host-initiated state changes:
- * - iff DATA transfer is active, carrier is "on"
- * - tx queueing enabled if open *and* carrier is "on"
- */
- netif_stop_queue (dev->net);
- netif_carrier_off (dev->net);
-
- SET_NETDEV_DEV (dev->net, &gadget->dev);
- status = register_netdev (dev->net);
+ status = usb_add_config(cdev, &eth_config_driver);
if (status < 0)
- goto fail1;
-
- INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
- INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,
- out_ep->name, in_ep->name,
- status_ep ? " STATUS " : "",
- status_ep ? status_ep->name : ""
- );
- INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- net->dev_addr [0], net->dev_addr [1],
- net->dev_addr [2], net->dev_addr [3],
- net->dev_addr [4], net->dev_addr [5]);
-
- if (cdc || rndis)
- INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->host_mac [0], dev->host_mac [1],
- dev->host_mac [2], dev->host_mac [3],
- dev->host_mac [4], dev->host_mac [5]);
-
- if (rndis) {
- u32 vendorID = 0;
-
- /* FIXME RNDIS vendor id == "vendor NIC code" == ? */
-
- dev->rndis_config = rndis_register (rndis_control_ack);
- if (dev->rndis_config < 0) {
-fail0:
- unregister_netdev (dev->net);
- status = -ENODEV;
- goto fail;
- }
+ goto fail;
- /* these set up a lot of the OIDs that RNDIS needs */
- rndis_set_host_mac (dev->rndis_config, dev->host_mac);
- if (rndis_set_param_dev (dev->rndis_config, dev->net,
- &dev->stats, &dev->cdc_filter))
- goto fail0;
- if (rndis_set_param_vendor(dev->rndis_config, vendorID,
- manufacturer))
- goto fail0;
- if (rndis_set_param_medium(dev->rndis_config,
- NDIS_MEDIUM_802_3, 0))
- goto fail0;
- INFO (dev, "RNDIS ready\n");
- }
+ INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
- return status;
+ return 0;
-fail1:
- dev_dbg(&gadget->dev, "register_netdev failed, %d\n", status);
fail:
- eth_unbind (gadget);
+ gether_cleanup();
return status;
}
-/*-------------------------------------------------------------------------*/
-
-static void
-eth_suspend (struct usb_gadget *gadget)
-{
- struct eth_dev *dev = get_gadget_data (gadget);
-
- DEBUG (dev, "suspend\n");
- dev->suspended = 1;
-}
-
-static void
-eth_resume (struct usb_gadget *gadget)
+static int __exit eth_unbind(struct usb_composite_dev *cdev)
{
- struct eth_dev *dev = get_gadget_data (gadget);
-
- DEBUG (dev, "resume\n");
- dev->suspended = 0;
+ gether_cleanup();
+ return 0;
}
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver eth_driver = {
- .speed = DEVSPEED,
-
- .function = (char *) driver_desc,
+static struct usb_composite_driver eth_driver = {
+ .name = "g_ether",
+ .dev = &device_desc,
+ .strings = dev_strings,
.bind = eth_bind,
- .unbind = eth_unbind,
-
- .setup = eth_setup,
- .disconnect = eth_disconnect,
-
- .suspend = eth_suspend,
- .resume = eth_resume,
-
- .driver = {
- .name = (char *) shortname,
- .owner = THIS_MODULE,
- },
+ .unbind = __exit_p(eth_unbind),
};
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell, Benedikt Spanger");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
+MODULE_AUTHOR("David Brownell, Benedikt Spanger");
+MODULE_LICENSE("GPL");
-
-static int __init init (void)
+static int __init init(void)
{
- return usb_gadget_register_driver (&eth_driver);
+ return usb_composite_register(&eth_driver);
}
-module_init (init);
+module_init(init);
-static void __exit cleanup (void)
+static void __exit cleanup(void)
{
- usb_gadget_unregister_driver (&eth_driver);
+ usb_composite_unregister(&eth_driver);
}
-module_exit (cleanup);
-
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
new file mode 100644
index 00000000000..d8faccf2789
--- /dev/null
+++ b/drivers/usb/gadget/f_acm.c
@@ -0,0 +1,589 @@
+/*
+ * f_acm.c -- USB CDC serial (ACM) function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This CDC ACM function support just wraps control functions and
+ * notifications around the generic serial-over-usb code.
+ *
+ * Because CDC ACM is standardized by the USB-IF, many host operating
+ * systems have drivers for it. Accordingly, ACM is the preferred
+ * interop solution for serial-port type connections. The control
+ * models are often not necessary, and in any case don't do much in
+ * this bare-bones implementation.
+ *
+ * Note that even MS-Windows has some support for ACM. However, that
+ * support is somewhat broken because when you use ACM in a composite
+ * device, having multiple interfaces confuses the poor OS. It doesn't
+ * seem to understand CDC Union descriptors. The new "association"
+ * descriptors (roughly equivalent to CDC Unions) may sometimes help.
+ */
+
+struct acm_ep_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+ struct usb_endpoint_descriptor *notify;
+};
+
+struct f_acm {
+ struct gserial port;
+ u8 ctrl_id, data_id;
+ u8 port_num;
+
+ struct usb_descriptor_header **fs_function;
+ struct acm_ep_descs fs;
+ struct usb_descriptor_header **hs_function;
+ struct acm_ep_descs hs;
+
+ struct usb_ep *notify;
+ struct usb_endpoint_descriptor *notify_desc;
+
+ struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
+ u16 port_handshake_bits;
+#define RS232_RTS (1 << 1) /* unused with full duplex */
+#define RS232_DTR (1 << 0) /* host is ready for data r/w */
+};
+
+static inline struct f_acm *func_to_acm(struct usb_function *f)
+{
+ return container_of(f, struct f_acm, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* notification endpoint uses smallish and infrequent fixed-size messages */
+
+#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
+#define GS_NOTIFY_MAXPACKET 8
+
+/* interface and class descriptors: */
+
+static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ /* .bInterfaceNumber = DYNAMIC */
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ /* .bInterfaceNumber = DYNAMIC */
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc acm_header_desc __initdata = {
+ .bLength = sizeof(acm_header_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+ .bcdCDC = __constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor
+acm_call_mgmt_descriptor __initdata = {
+ .bLength = sizeof(acm_call_mgmt_descriptor),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
+ .bmCapabilities = 0,
+ /* .bDataInterface = DYNAMIC */
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+ .bLength = sizeof(acm_descriptor),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
+ .bmCapabilities = (1 << 1),
+};
+
+static struct usb_cdc_union_desc acm_union_desc __initdata = {
+ .bLength = sizeof(acm_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
+};
+
+static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *acm_fs_function[] __initdata = {
+ (struct usb_descriptor_header *) &acm_control_interface_desc,
+ (struct usb_descriptor_header *) &acm_header_desc,
+ (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &acm_descriptor,
+ (struct usb_descriptor_header *) &acm_union_desc,
+ (struct usb_descriptor_header *) &acm_fs_notify_desc,
+ (struct usb_descriptor_header *) &acm_data_interface_desc,
+ (struct usb_descriptor_header *) &acm_fs_in_desc,
+ (struct usb_descriptor_header *) &acm_fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *acm_hs_function[] __initdata = {
+ (struct usb_descriptor_header *) &acm_control_interface_desc,
+ (struct usb_descriptor_header *) &acm_header_desc,
+ (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &acm_descriptor,
+ (struct usb_descriptor_header *) &acm_union_desc,
+ (struct usb_descriptor_header *) &acm_hs_notify_desc,
+ (struct usb_descriptor_header *) &acm_data_interface_desc,
+ (struct usb_descriptor_header *) &acm_hs_in_desc,
+ (struct usb_descriptor_header *) &acm_hs_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+#define ACM_CTRL_IDX 0
+#define ACM_DATA_IDX 1
+
+/* static strings, in UTF-8 */
+static struct usb_string acm_string_defs[] = {
+ [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
+ [ACM_DATA_IDX].s = "CDC ACM Data",
+ { /* ZEROES END LIST */ },
+};
+
+static struct usb_gadget_strings acm_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = acm_string_defs,
+};
+
+static struct usb_gadget_strings *acm_strings[] = {
+ &acm_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM control ... data handling is delegated to tty library code.
+ * The main task of this function is to activate and deactivate
+ * that code based on device state; track parameters like line
+ * speed, handshake state, and so on; and issue notifications.
+ */
+
+static void acm_complete_set_line_coding(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct f_acm *acm = ep->driver_data;
+ struct usb_composite_dev *cdev = acm->port.func.config->cdev;
+
+ if (req->status != 0) {
+ DBG(cdev, "acm ttyGS%d completion, err %d\n",
+ acm->port_num, req->status);
+ return;
+ }
+
+ /* normal completion */
+ if (req->actual != sizeof(acm->port_line_coding)) {
+ DBG(cdev, "acm ttyGS%d short resp, len %d\n",
+ acm->port_num, req->actual);
+ usb_ep_set_halt(ep);
+ } else {
+ struct usb_cdc_line_coding *value = req->buf;
+
+ /* REVISIT: we currently just remember this data.
+ * If we change that, (a) validate it first, then
+ * (b) update whatever hardware needs updating,
+ * (c) worry about locking. This is information on
+ * the order of 9600-8-N-1 ... most of which means
+ * nothing unless we control a real RS232 line.
+ */
+ acm->port_line_coding = *value;
+ }
+}
+
+static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_acm *acm = func_to_acm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything except
+ * CDC class messages; interface activation uses set_alt().
+ */
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+ /* SET_LINE_CODING ... just read and save what the host sends */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_SET_LINE_CODING:
+ if (w_length != sizeof(struct usb_cdc_line_coding)
+ || w_index != acm->ctrl_id)
+ goto invalid;
+
+ value = w_length;
+ cdev->gadget->ep0->driver_data = acm;
+ req->complete = acm_complete_set_line_coding;
+ break;
+
+ /* GET_LINE_CODING ... return what host sent, or initial value */
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_GET_LINE_CODING:
+ if (w_index != acm->ctrl_id)
+ goto invalid;
+
+ value = min_t(unsigned, w_length,
+ sizeof(struct usb_cdc_line_coding));
+ memcpy(req->buf, &acm->port_line_coding, value);
+ break;
+
+ /* SET_CONTROL_LINE_STATE ... save what the host sent */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
+ if (w_index != acm->ctrl_id)
+ goto invalid;
+
+ value = 0;
+
+ /* FIXME we should not allow data to flow until the
+ * host sets the RS232_DTR bit; and when it clears
+ * that bit, we should return to that no-flow state.
+ */
+ acm->port_handshake_bits = w_value;
+ break;
+
+ default:
+invalid:
+ VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
+ acm->port_num, ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "acm response on ttyGS%d, err %d\n",
+ acm->port_num, value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_acm *acm = func_to_acm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt == 0, so this is an activation or a reset */
+
+ if (intf == acm->ctrl_id) {
+ /* REVISIT this may need more work when we start to
+ * send notifications ...
+ */
+ if (acm->notify->driver_data) {
+ VDBG(cdev, "reset acm control interface %d\n", intf);
+ usb_ep_disable(acm->notify);
+ } else {
+ VDBG(cdev, "init acm ctrl interface %d\n", intf);
+ acm->notify_desc = ep_choose(cdev->gadget,
+ acm->hs.notify,
+ acm->fs.notify);
+ }
+ usb_ep_enable(acm->notify, acm->notify_desc);
+ acm->notify->driver_data = acm;
+
+ } else if (intf == acm->data_id) {
+ if (acm->port.in->driver_data) {
+ DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
+ gserial_disconnect(&acm->port);
+ } else {
+ DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
+ acm->port.in_desc = ep_choose(cdev->gadget,
+ acm->hs.in, acm->fs.in);
+ acm->port.out_desc = ep_choose(cdev->gadget,
+ acm->hs.out, acm->fs.out);
+ }
+ gserial_connect(&acm->port, acm->port_num);
+
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static void acm_disable(struct usb_function *f)
+{
+ struct f_acm *acm = func_to_acm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
+ gserial_disconnect(&acm->port);
+ usb_ep_disable(acm->notify);
+ acm->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM function driver setup/binding */
+static int __init
+acm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_acm *acm = func_to_acm(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs, and patch descriptors */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ acm->ctrl_id = status;
+
+ acm_control_interface_desc.bInterfaceNumber = status;
+ acm_union_desc .bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ acm->data_id = status;
+
+ acm_data_interface_desc.bInterfaceNumber = status;
+ acm_union_desc.bSlaveInterface0 = status;
+ acm_call_mgmt_descriptor.bDataInterface = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
+ if (!ep)
+ goto fail;
+ acm->port.in = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
+ if (!ep)
+ goto fail;
+ acm->port.out = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
+ if (!ep)
+ goto fail;
+ acm->notify = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(acm_fs_function);
+
+ acm->fs.in = usb_find_endpoint(acm_fs_function,
+ f->descriptors, &acm_fs_in_desc);
+ acm->fs.out = usb_find_endpoint(acm_fs_function,
+ f->descriptors, &acm_fs_out_desc);
+ acm->fs.notify = usb_find_endpoint(acm_fs_function,
+ f->descriptors, &acm_fs_notify_desc);
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ acm_hs_in_desc.bEndpointAddress =
+ acm_fs_in_desc.bEndpointAddress;
+ acm_hs_out_desc.bEndpointAddress =
+ acm_fs_out_desc.bEndpointAddress;
+ acm_hs_notify_desc.bEndpointAddress =
+ acm_fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+
+ acm->hs.in = usb_find_endpoint(acm_hs_function,
+ f->hs_descriptors, &acm_hs_in_desc);
+ acm->hs.out = usb_find_endpoint(acm_hs_function,
+ f->hs_descriptors, &acm_hs_out_desc);
+ acm->hs.notify = usb_find_endpoint(acm_hs_function,
+ f->hs_descriptors, &acm_hs_notify_desc);
+ }
+
+ /* FIXME provide a callback for triggering notifications */
+
+ DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+ acm->port_num,
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ acm->port.in->name, acm->port.out->name,
+ acm->notify->name);
+ return 0;
+
+fail:
+ /* we might as well release our claims on endpoints */
+ if (acm->notify)
+ acm->notify->driver_data = NULL;
+ if (acm->port.out)
+ acm->port.out->driver_data = NULL;
+ if (acm->port.in)
+ acm->port.in->driver_data = NULL;
+
+ ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
+
+ return status;
+}
+
+static void
+acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+ kfree(func_to_acm(f));
+}
+
+/* Some controllers can't support CDC ACM ... */
+static inline bool can_support_cdc(struct usb_configuration *c)
+{
+ /* SH3 doesn't support multiple interfaces */
+ if (gadget_is_sh(c->cdev->gadget))
+ return false;
+
+ /* sa1100 doesn't have a third interrupt endpoint */
+ if (gadget_is_sa1100(c->cdev->gadget))
+ return false;
+
+ /* everything else is *probably* fine ... */
+ return true;
+}
+
+/**
+ * acm_bind_config - add a CDC ACM function to a configuration
+ * @c: the configuration to support the CDC ACM instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds. Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
+{
+ struct f_acm *acm;
+ int status;
+
+ if (!can_support_cdc(c))
+ return -EINVAL;
+
+ /* REVISIT might want instance-specific strings to help
+ * distinguish instances ...
+ */
+
+ /* maybe allocate device-global string IDs, and patch descriptors */
+ if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ acm_string_defs[ACM_CTRL_IDX].id = status;
+
+ acm_control_interface_desc.iInterface = status;
+
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ acm_string_defs[ACM_DATA_IDX].id = status;
+
+ acm_data_interface_desc.iInterface = status;
+ }
+
+ /* allocate and initialize one new instance */
+ acm = kzalloc(sizeof *acm, GFP_KERNEL);
+ if (!acm)
+ return -ENOMEM;
+
+ acm->port_num = port_num;
+
+ acm->port.func.name = "acm";
+ acm->port.func.strings = acm_strings;
+ /* descriptors are per-instance copies */
+ acm->port.func.bind = acm_bind;
+ acm->port.func.unbind = acm_unbind;
+ acm->port.func.set_alt = acm_set_alt;
+ acm->port.func.setup = acm_setup;
+ acm->port.func.disable = acm_disable;
+
+ status = usb_add_function(c, &acm->port.func);
+ if (status)
+ kfree(acm);
+ return status;
+}
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
new file mode 100644
index 00000000000..0822e9d7693
--- /dev/null
+++ b/drivers/usb/gadget/f_ecm.c
@@ -0,0 +1,833 @@
+/*
+ * f_ecm.c -- USB CDC Ethernet (ECM) link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
+ * Ethernet link. The data transfer model is simple (packets sent and
+ * received over bulk endpoints using normal short packet termination),
+ * and the control model exposes various data and optional notifications.
+ *
+ * ECM is well standardized and (except for Microsoft) supported by most
+ * operating systems with USB host support. It's the preferred interop
+ * solution for Ethernet over USB, at least for firmware based solutions.
+ * (Hardware solutions tend to be more minimalist.) A newer and simpler
+ * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on.
+ *
+ * Note that ECM requires the use of "alternate settings" for its data
+ * interface. This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+struct ecm_ep_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+ struct usb_endpoint_descriptor *notify;
+};
+
+enum ecm_notify_state {
+ ECM_NOTIFY_NONE, /* don't notify */
+ ECM_NOTIFY_CONNECT, /* issue CONNECT next */
+ ECM_NOTIFY_SPEED, /* issue SPEED_CHANGE next */
+};
+
+struct f_ecm {
+ struct gether port;
+ u8 ctrl_id, data_id;
+
+ char ethaddr[14];
+
+ struct usb_descriptor_header **fs_function;
+ struct ecm_ep_descs fs;
+ struct usb_descriptor_header **hs_function;
+ struct ecm_ep_descs hs;
+
+ struct usb_ep *notify;
+ struct usb_endpoint_descriptor *notify_desc;
+ struct usb_request *notify_req;
+ u8 notify_state;
+ bool is_open;
+
+ /* FIXME is_open needs some irq-ish locking
+ * ... possibly the same as port.ioport
+ */
+};
+
+static inline struct f_ecm *func_to_ecm(struct usb_function *f)
+{
+ return container_of(f, struct f_ecm, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned bitrate(struct usb_gadget *g)
+{
+ if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+ return 13 * 512 * 8 * 1000 * 8;
+ else
+ return 19 * 64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Include the status endpoint if we can, even though it's optional.
+ *
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ *
+ * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
+ * if they ignore the connect/disconnect notifications that real aether
+ * can provide. More advanced cdc configurations might want to support
+ * encapsulated commands (vendor-specific, using control-OUT).
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor ecm_control_intf __initdata = {
+ .bLength = sizeof ecm_control_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ /* status endpoint is optional; this could be patched later */
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+ .bLength = sizeof header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+
+ .bcdCDC = __constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc ecm_union_desc __initdata = {
+ .bLength = sizeof(ecm_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+ .bLength = sizeof ether_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
+
+ /* this descriptor actually adds value, surprise! */
+ /* .iMACAddress = DYNAMIC */
+ .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */
+ .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN),
+ .wNumberMCFilters = __constant_cpu_to_le16(0),
+ .bNumberPowerFilters = 0,
+};
+
+/* the default data interface has no endpoints ... */
+
+static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
+ .bLength = sizeof ecm_data_nop_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor ecm_data_intf __initdata = {
+ .bLength = sizeof ecm_data_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+ /* CDC ECM control descriptors */
+ (struct usb_descriptor_header *) &ecm_control_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &ecm_union_desc,
+ (struct usb_descriptor_header *) &ether_desc,
+ /* NOTE: status endpoint might need to be removed */
+ (struct usb_descriptor_header *) &fs_notify_desc,
+ /* data interface, altsettings 0 and 1 */
+ (struct usb_descriptor_header *) &ecm_data_nop_intf,
+ (struct usb_descriptor_header *) &ecm_data_intf,
+ (struct usb_descriptor_header *) &fs_in_desc,
+ (struct usb_descriptor_header *) &fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+ /* CDC ECM control descriptors */
+ (struct usb_descriptor_header *) &ecm_control_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &ecm_union_desc,
+ (struct usb_descriptor_header *) &ether_desc,
+ /* NOTE: status endpoint might need to be removed */
+ (struct usb_descriptor_header *) &hs_notify_desc,
+ /* data interface, altsettings 0 and 1 */
+ (struct usb_descriptor_header *) &ecm_data_nop_intf,
+ (struct usb_descriptor_header *) &ecm_data_intf,
+ (struct usb_descriptor_header *) &hs_in_desc,
+ (struct usb_descriptor_header *) &hs_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string ecm_string_defs[] = {
+ [0].s = "CDC Ethernet Control Model (ECM)",
+ [1].s = NULL /* DYNAMIC */,
+ [2].s = "CDC Ethernet Data",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings ecm_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = ecm_string_defs,
+};
+
+static struct usb_gadget_strings *ecm_strings[] = {
+ &ecm_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void ecm_do_notify(struct f_ecm *ecm)
+{
+ struct usb_request *req = ecm->notify_req;
+ struct usb_cdc_notification *event;
+ struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
+ __le32 *data;
+ int status;
+
+ /* notification already in flight? */
+ if (!req)
+ return;
+
+ event = req->buf;
+ switch (ecm->notify_state) {
+ case ECM_NOTIFY_NONE:
+ return;
+
+ case ECM_NOTIFY_CONNECT:
+ event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+ if (ecm->is_open)
+ event->wValue = cpu_to_le16(1);
+ else
+ event->wValue = cpu_to_le16(0);
+ event->wLength = 0;
+ req->length = sizeof *event;
+
+ DBG(cdev, "notify connect %s\n",
+ ecm->is_open ? "true" : "false");
+ ecm->notify_state = ECM_NOTIFY_SPEED;
+ break;
+
+ case ECM_NOTIFY_SPEED:
+ event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+ event->wValue = cpu_to_le16(0);
+ event->wLength = cpu_to_le16(8);
+ req->length = STATUS_BYTECOUNT;
+
+ /* SPEED_CHANGE data is up/down speeds in bits/sec */
+ data = req->buf + sizeof *event;
+ data[0] = cpu_to_le32(bitrate(cdev->gadget));
+ data[1] = data[0];
+
+ DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+ ecm->notify_state = ECM_NOTIFY_NONE;
+ break;
+ }
+ event->bmRequestType = 0xA1;
+ event->wIndex = cpu_to_le16(ecm->ctrl_id);
+
+ ecm->notify_req = NULL;
+ status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
+ if (status < 0) {
+ ecm->notify_req = req;
+ DBG(cdev, "notify --> %d\n", status);
+ }
+}
+
+static void ecm_notify(struct f_ecm *ecm)
+{
+ /* NOTE on most versions of Linux, host side cdc-ethernet
+ * won't listen for notifications until its netdevice opens.
+ * The first notification then sits in the FIFO for a long
+ * time, and the second one is queued.
+ */
+ ecm->notify_state = ECM_NOTIFY_CONNECT;
+ ecm_do_notify(ecm);
+}
+
+static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_ecm *ecm = req->context;
+ struct usb_composite_dev *cdev = ecm->port.func.config->cdev;
+ struct usb_cdc_notification *event = req->buf;
+
+ switch (req->status) {
+ case 0:
+ /* no fault */
+ break;
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ ecm->notify_state = ECM_NOTIFY_NONE;
+ break;
+ default:
+ DBG(cdev, "event %02x --> %d\n",
+ event->bNotificationType, req->status);
+ break;
+ }
+ ecm->notify_req = req;
+ ecm_do_notify(ecm);
+}
+
+static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_ecm *ecm = func_to_ecm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything except
+ * CDC class messages; interface activation uses set_alt().
+ */
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SET_ETHERNET_PACKET_FILTER:
+ /* see 6.2.30: no data, wIndex = interface,
+ * wValue = packet filter bitmap
+ */
+ if (w_length != 0 || w_index != ecm->ctrl_id)
+ goto invalid;
+ DBG(cdev, "packet filter %02x\n", w_value);
+ /* REVISIT locking of cdc_filter. This assumes the UDC
+ * driver won't have a concurrent packet TX irq running on
+ * another CPU; or that if it does, this write is atomic...
+ */
+ ecm->port.cdc_filter = w_value;
+ value = 0;
+ break;
+
+ /* and optionally:
+ * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
+ * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
+ * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+ * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_STATISTIC:
+ */
+
+ default:
+invalid:
+ DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "ecm req %02x.%02x response err %d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+
+static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_ecm *ecm = func_to_ecm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* Control interface has only altsetting 0 */
+ if (intf == ecm->ctrl_id) {
+ if (alt != 0)
+ goto fail;
+
+ if (ecm->notify->driver_data) {
+ VDBG(cdev, "reset ecm control %d\n", intf);
+ usb_ep_disable(ecm->notify);
+ } else {
+ VDBG(cdev, "init ecm ctrl %d\n", intf);
+ ecm->notify_desc = ep_choose(cdev->gadget,
+ ecm->hs.notify,
+ ecm->fs.notify);
+ }
+ usb_ep_enable(ecm->notify, ecm->notify_desc);
+ ecm->notify->driver_data = ecm;
+
+ /* Data interface has two altsettings, 0 and 1 */
+ } else if (intf == ecm->data_id) {
+ if (alt > 1)
+ goto fail;
+
+ if (ecm->port.in_ep->driver_data) {
+ DBG(cdev, "reset ecm\n");
+ gether_disconnect(&ecm->port);
+ }
+
+ if (!ecm->port.in) {
+ DBG(cdev, "init ecm\n");
+ ecm->port.in = ep_choose(cdev->gadget,
+ ecm->hs.in, ecm->fs.in);
+ ecm->port.out = ep_choose(cdev->gadget,
+ ecm->hs.out, ecm->fs.out);
+ }
+
+ /* CDC Ethernet only sends data in non-default altsettings.
+ * Changing altsettings resets filters, statistics, etc.
+ */
+ if (alt == 1) {
+ struct net_device *net;
+
+ /* Enable zlps by default for ECM conformance;
+ * override for musb_hdrc (avoids txdma ovhead)
+ * and sa1100 (can't).
+ */
+ ecm->port.is_zlp_ok = !(
+ gadget_is_sa1100(cdev->gadget)
+ || gadget_is_musbhdrc(cdev->gadget)
+ );
+ ecm->port.cdc_filter = DEFAULT_FILTER;
+ DBG(cdev, "activate ecm\n");
+ net = gether_connect(&ecm->port);
+ if (IS_ERR(net))
+ return PTR_ERR(net);
+ }
+
+ /* NOTE this can be a minor disagreement with the ECM spec,
+ * which says speed notifications will "always" follow
+ * connection notifications. But we allow one connect to
+ * follow another (if the first is in flight), and instead
+ * just guarantee that a speed notification is always sent.
+ */
+ ecm_notify(ecm);
+ } else
+ goto fail;
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+/* Because the data interface supports multiple altsettings,
+ * this ECM function *MUST* implement a get_alt() method.
+ */
+static int ecm_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_ecm *ecm = func_to_ecm(f);
+
+ if (intf == ecm->ctrl_id)
+ return 0;
+ return ecm->port.in_ep->driver_data ? 1 : 0;
+}
+
+static void ecm_disable(struct usb_function *f)
+{
+ struct f_ecm *ecm = func_to_ecm(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "ecm deactivated\n");
+
+ if (ecm->port.in_ep->driver_data)
+ gether_disconnect(&ecm->port);
+
+ if (ecm->notify->driver_data) {
+ usb_ep_disable(ecm->notify);
+ ecm->notify->driver_data = NULL;
+ ecm->notify_desc = NULL;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Callbacks let us notify the host about connect/disconnect when the
+ * net device is opened or closed.
+ *
+ * For testing, note that link states on this side include both opened
+ * and closed variants of:
+ *
+ * - disconnected/unconfigured
+ * - configured but inactive (data alt 0)
+ * - configured and active (data alt 1)
+ *
+ * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
+ * SET_INTERFACE (altsetting). Remember also that "configured" doesn't
+ * imply the host is actually polling the notification endpoint, and
+ * likewise that "active" doesn't imply it's actually using the data
+ * endpoints for traffic.
+ */
+
+static void ecm_open(struct gether *geth)
+{
+ struct f_ecm *ecm = func_to_ecm(&geth->func);
+
+ DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+ ecm->is_open = true;
+ ecm_notify(ecm);
+}
+
+static void ecm_close(struct gether *geth)
+{
+ struct f_ecm *ecm = func_to_ecm(&geth->func);
+
+ DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+ ecm->is_open = false;
+ ecm_notify(ecm);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+ecm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_ecm *ecm = func_to_ecm(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ ecm->ctrl_id = status;
+
+ ecm_control_intf.bInterfaceNumber = status;
+ ecm_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ ecm->data_id = status;
+
+ ecm_data_nop_intf.bInterfaceNumber = status;
+ ecm_data_intf.bInterfaceNumber = status;
+ ecm_union_desc.bSlaveInterface0 = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+ if (!ep)
+ goto fail;
+ ecm->port.in_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+ if (!ep)
+ goto fail;
+ ecm->port.out_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* NOTE: a status/notification endpoint is *OPTIONAL* but we
+ * don't treat it that way. It's simpler, and some newer CDC
+ * profiles (wireless handsets) no longer treat it as optional.
+ */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+ if (!ep)
+ goto fail;
+ ecm->notify = ep;
+ ep->driver_data = cdev; /* claim */
+
+ status = -ENOMEM;
+
+ /* allocate notification request and buffer */
+ ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+ if (!ecm->notify_req)
+ goto fail;
+ ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+ if (!ecm->notify_req->buf)
+ goto fail;
+ ecm->notify_req->context = ecm;
+ ecm->notify_req->complete = ecm_notify_complete;
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(eth_fs_function);
+ if (!f->descriptors)
+ goto fail;
+
+ ecm->fs.in = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_in_desc);
+ ecm->fs.out = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_out_desc);
+ ecm->fs.notify = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_notify_desc);
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_in_desc.bEndpointAddress =
+ fs_in_desc.bEndpointAddress;
+ hs_out_desc.bEndpointAddress =
+ fs_out_desc.bEndpointAddress;
+ hs_notify_desc.bEndpointAddress =
+ fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+ if (!f->hs_descriptors)
+ goto fail;
+
+ ecm->hs.in = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_in_desc);
+ ecm->hs.out = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_out_desc);
+ ecm->hs.notify = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_notify_desc);
+ }
+
+ /* NOTE: all that is done without knowing or caring about
+ * the network link ... which is unavailable to this code
+ * until we're activated via set_alt().
+ */
+
+ ecm->port.open = ecm_open;
+ ecm->port.close = ecm_close;
+
+ DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ ecm->port.in_ep->name, ecm->port.out_ep->name,
+ ecm->notify->name);
+ return 0;
+
+fail:
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
+ if (ecm->notify_req) {
+ kfree(ecm->notify_req->buf);
+ usb_ep_free_request(ecm->notify, ecm->notify_req);
+ }
+
+ /* we might as well release our claims on endpoints */
+ if (ecm->notify)
+ ecm->notify->driver_data = NULL;
+ if (ecm->port.out)
+ ecm->port.out_ep->driver_data = NULL;
+ if (ecm->port.in)
+ ecm->port.in_ep->driver_data = NULL;
+
+ ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+ return status;
+}
+
+static void
+ecm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_ecm *ecm = func_to_ecm(f);
+
+ DBG(c->cdev, "ecm unbind\n");
+
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+
+ kfree(ecm->notify_req->buf);
+ usb_ep_free_request(ecm->notify, ecm->notify_req);
+
+ ecm_string_defs[1].s = NULL;
+ kfree(ecm);
+}
+
+/**
+ * ecm_bind_config - add CDC Ethernet network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+ struct f_ecm *ecm;
+ int status;
+
+ if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
+ return -EINVAL;
+
+ /* maybe allocate device-global string IDs */
+ if (ecm_string_defs[0].id == 0) {
+
+ /* control interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ ecm_string_defs[0].id = status;
+ ecm_control_intf.iInterface = status;
+
+ /* data interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ ecm_string_defs[2].id = status;
+ ecm_data_intf.iInterface = status;
+
+ /* MAC address */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ ecm_string_defs[1].id = status;
+ ether_desc.iMACAddress = status;
+ }
+
+ /* allocate and initialize one new instance */
+ ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
+ if (!ecm)
+ return -ENOMEM;
+
+ /* export host's Ethernet address in CDC format */
+ snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
+ "%02X%02X%02X%02X%02X%02X",
+ ethaddr[0], ethaddr[1], ethaddr[2],
+ ethaddr[3], ethaddr[4], ethaddr[5]);
+ ecm_string_defs[1].s = ecm->ethaddr;
+
+ ecm->port.cdc_filter = DEFAULT_FILTER;
+
+ ecm->port.func.name = "cdc_ethernet";
+ ecm->port.func.strings = ecm_strings;
+ /* descriptors are per-instance copies */
+ ecm->port.func.bind = ecm_bind;
+ ecm->port.func.unbind = ecm_unbind;
+ ecm->port.func.set_alt = ecm_set_alt;
+ ecm->port.func.get_alt = ecm_get_alt;
+ ecm->port.func.setup = ecm_setup;
+ ecm->port.func.disable = ecm_disable;
+
+ status = usb_add_function(c, &ecm->port.func);
+ if (status) {
+ ecm_string_defs[1].s = NULL;
+ kfree(ecm);
+ }
+ return status;
+}
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
new file mode 100644
index 00000000000..eda4cde72c8
--- /dev/null
+++ b/drivers/usb/gadget/f_loopback.c
@@ -0,0 +1,381 @@
+/*
+ * f_loopback.c - USB peripheral loopback configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
+ *
+ * This takes messages of various sizes written OUT to a device, and loops
+ * them back so they can be read IN from it. It has been used by certain
+ * test applications. It supports limited testing of data queueing logic.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices. However, it
+ * can be combined with other independent configurations.
+ */
+struct f_loopback {
+ struct usb_function function;
+
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep;
+};
+
+static inline struct f_loopback *func_to_loop(struct usb_function *f)
+{
+ return container_of(f, struct f_loopback, function);
+}
+
+static unsigned qlen = 32;
+module_param(qlen, uint, 0);
+MODULE_PARM_DESC(qlenn, "depth of loopback queue");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor loopback_intf = {
+ .bLength = sizeof loopback_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_loopback_descs[] = {
+ (struct usb_descriptor_header *) &loopback_intf,
+ (struct usb_descriptor_header *) &fs_sink_desc,
+ (struct usb_descriptor_header *) &fs_source_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_loopback_descs[] = {
+ (struct usb_descriptor_header *) &loopback_intf,
+ (struct usb_descriptor_header *) &hs_source_desc,
+ (struct usb_descriptor_header *) &hs_sink_desc,
+ NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_loopback[] = {
+ [0].s = "loop input to output",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_loop = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_loopback,
+};
+
+static struct usb_gadget_strings *loopback_strings[] = {
+ &stringtab_loop,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init
+loopback_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_loopback *loop = func_to_loop(f);
+ int id;
+
+ /* allocate interface ID(s) */
+ id = usb_interface_id(c, f);
+ if (id < 0)
+ return id;
+ loopback_intf.bInterfaceNumber = id;
+
+ /* allocate endpoints */
+
+ loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+ if (!loop->in_ep) {
+autoconf_fail:
+ ERROR(cdev, "%s: can't autoconfigure on %s\n",
+ f->name, cdev->gadget->name);
+ return -ENODEV;
+ }
+ loop->in_ep->driver_data = cdev; /* claim */
+
+ loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+ if (!loop->out_ep)
+ goto autoconf_fail;
+ loop->out_ep->driver_data = cdev; /* claim */
+
+ /* support high speed hardware */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_source_desc.bEndpointAddress =
+ fs_source_desc.bEndpointAddress;
+ hs_sink_desc.bEndpointAddress =
+ fs_sink_desc.bEndpointAddress;
+ f->hs_descriptors = hs_loopback_descs;
+ }
+
+ DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ f->name, loop->in_ep->name, loop->out_ep->name);
+ return 0;
+}
+
+static void
+loopback_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ kfree(func_to_loop(f));
+}
+
+static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_loopback *loop = ep->driver_data;
+ struct usb_composite_dev *cdev = loop->function.config->cdev;
+ int status = req->status;
+
+ switch (status) {
+
+ case 0: /* normal completion? */
+ if (ep == loop->out_ep) {
+ /* loop this OUT packet back IN to the host */
+ req->zero = (req->actual < req->length);
+ req->length = req->actual;
+ status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
+ if (status == 0)
+ return;
+
+ /* "should never get here" */
+ ERROR(cdev, "can't loop %s to %s: %d\n",
+ ep->name, loop->in_ep->name,
+ status);
+ }
+
+ /* queue the buffer for some later OUT packet */
+ req->length = buflen;
+ status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
+ if (status == 0)
+ return;
+
+ /* "should never get here" */
+ /* FALLTHROUGH */
+
+ default:
+ ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
+ status, req->actual, req->length);
+ /* FALLTHROUGH */
+
+ /* NOTE: since this driver doesn't maintain an explicit record
+ * of requests it submitted (just maintains qlen count), we
+ * rely on the hardware driver to clean up on disconnect or
+ * endpoint disable.
+ */
+ case -ECONNABORTED: /* hardware forced ep reset */
+ case -ECONNRESET: /* request dequeued */
+ case -ESHUTDOWN: /* disconnect from host */
+ free_ep_req(ep, req);
+ return;
+ }
+}
+
+static void disable_loopback(struct f_loopback *loop)
+{
+ struct usb_composite_dev *cdev;
+
+ cdev = loop->function.config->cdev;
+ disable_endpoints(cdev, loop->in_ep, loop->out_ep);
+ VDBG(cdev, "%s disabled\n", loop->function.name);
+}
+
+static int
+enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
+{
+ int result = 0;
+ const struct usb_endpoint_descriptor *src, *sink;
+ struct usb_ep *ep;
+ struct usb_request *req;
+ unsigned i;
+
+ src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+ sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+ /* one endpoint writes data back IN to the host */
+ ep = loop->in_ep;
+ result = usb_ep_enable(ep, src);
+ if (result < 0)
+ return result;
+ ep->driver_data = loop;
+
+ /* one endpoint just reads OUT packets */
+ ep = loop->out_ep;
+ result = usb_ep_enable(ep, sink);
+ if (result < 0) {
+fail0:
+ ep = loop->in_ep;
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ return result;
+ }
+ ep->driver_data = loop;
+
+ /* allocate a bunch of read buffers and queue them all at once.
+ * we buffer at most 'qlen' transfers; fewer if any need more
+ * than 'buflen' bytes each.
+ */
+ for (i = 0; i < qlen && result == 0; i++) {
+ req = alloc_ep_req(ep);
+ if (req) {
+ req->complete = loopback_complete;
+ result = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (result)
+ ERROR(cdev, "%s queue req --> %d\n",
+ ep->name, result);
+ } else {
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ result = -ENOMEM;
+ goto fail0;
+ }
+ }
+
+ DBG(cdev, "%s enabled\n", loop->function.name);
+ return result;
+}
+
+static int loopback_set_alt(struct usb_function *f,
+ unsigned intf, unsigned alt)
+{
+ struct f_loopback *loop = func_to_loop(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt is zero */
+ if (loop->in_ep->driver_data)
+ disable_loopback(loop);
+ return enable_loopback(cdev, loop);
+}
+
+static void loopback_disable(struct usb_function *f)
+{
+ struct f_loopback *loop = func_to_loop(f);
+
+ disable_loopback(loop);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init loopback_bind_config(struct usb_configuration *c)
+{
+ struct f_loopback *loop;
+ int status;
+
+ loop = kzalloc(sizeof *loop, GFP_KERNEL);
+ if (!loop)
+ return -ENOMEM;
+
+ loop->function.name = "loopback";
+ loop->function.descriptors = fs_loopback_descs;
+ loop->function.bind = loopback_bind;
+ loop->function.unbind = loopback_unbind;
+ loop->function.set_alt = loopback_set_alt;
+ loop->function.disable = loopback_disable;
+
+ status = usb_add_function(c, &loop->function);
+ if (status)
+ kfree(loop);
+ return status;
+}
+
+static struct usb_configuration loopback_driver = {
+ .label = "loopback",
+ .strings = loopback_strings,
+ .bind = loopback_bind_config,
+ .bConfigurationValue = 2,
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
+ /* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * loopback_add - add a loopback testing configuration to a device
+ * @cdev: the device to support the loopback configuration
+ */
+int __init loopback_add(struct usb_composite_dev *cdev)
+{
+ int id;
+
+ /* allocate string ID(s) */
+ id = usb_string_id(cdev);
+ if (id < 0)
+ return id;
+ strings_loopback[0].id = id;
+
+ loopback_intf.iInterface = id;
+ loopback_driver.iConfiguration = id;
+
+ /* support OTG systems */
+ if (gadget_is_otg(cdev->gadget)) {
+ loopback_driver.descriptors = otg_desc;
+ loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ }
+
+ return usb_add_config(cdev, &loopback_driver);
+}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
new file mode 100644
index 00000000000..61652f0f13f
--- /dev/null
+++ b/drivers/usb/gadget/f_rndis.c
@@ -0,0 +1,827 @@
+/*
+ * f_rndis.c -- RNDIS link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include <asm/atomic.h>
+
+#include "u_ether.h"
+#include "rndis.h"
+
+
+/*
+ * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
+ * been promoted instead of the standard CDC Ethernet. The published RNDIS
+ * spec is ambiguous, incomplete, and needlessly complex. Variants such as
+ * ActiveSync have even worse status in terms of specification.
+ *
+ * In short: it's a protocol controlled by (and for) Microsoft, not for an
+ * Open ecosystem or markets. Linux supports it *only* because Microsoft
+ * doesn't support the CDC Ethernet standard.
+ *
+ * The RNDIS data transfer model is complex, with multiple Ethernet packets
+ * per USB message, and out of band data. The control model is built around
+ * what's essentially an "RNDIS RPC" protocol. It's all wrapped in a CDC ACM
+ * (modem, not Ethernet) veneer, with those ACM descriptors being entirely
+ * useless (they're ignored). RNDIS expects to be the only function in its
+ * configuration, so it's no real help if you need composite devices; and
+ * it expects to be the first configuration too.
+ *
+ * There is a single technical advantage of RNDIS over CDC Ethernet, if you
+ * discount the fluff that its RPC can be made to deliver: it doesn't need
+ * a NOP altsetting for the data interface. That lets it work on some of the
+ * "so smart it's stupid" hardware which takes over configuration changes
+ * from the software, and adds restrictions like "no altsettings".
+ *
+ * Unfortunately MSFT's RNDIS drivers are buggy. They hang or oops, and
+ * have all sorts of contrary-to-specification oddities that can prevent
+ * them from working sanely. Since bugfixes (or accurate specs, letting
+ * Linux work around those bugs) are unlikely to ever come from MSFT, you
+ * may want to avoid using RNDIS on purely operational grounds.
+ *
+ * Omissions from the RNDIS 1.0 specification include:
+ *
+ * - Power management ... references data that's scattered around lots
+ * of other documentation, which is incorrect/incomplete there too.
+ *
+ * - There are various undocumented protocol requirements, like the need
+ * to send garbage in some control-OUT messages.
+ *
+ * - MS-Windows drivers sometimes emit undocumented requests.
+ */
+
+struct rndis_ep_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+ struct usb_endpoint_descriptor *notify;
+};
+
+struct f_rndis {
+ struct gether port;
+ u8 ctrl_id, data_id;
+ u8 ethaddr[ETH_ALEN];
+ int config;
+
+ struct usb_descriptor_header **fs_function;
+ struct rndis_ep_descs fs;
+ struct usb_descriptor_header **hs_function;
+ struct rndis_ep_descs hs;
+
+ struct usb_ep *notify;
+ struct usb_endpoint_descriptor *notify_desc;
+ struct usb_request *notify_req;
+ atomic_t notify_count;
+};
+
+static inline struct f_rndis *func_to_rndis(struct usb_function *f)
+{
+ return container_of(f, struct f_rndis, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static unsigned int bitrate(struct usb_gadget *g)
+{
+ if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+ return 13 * 512 * 8 * 1000 * 8;
+ else
+ return 19 * 64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT 8 /* 8 bytes data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor rndis_control_intf __initdata = {
+ .bLength = sizeof rndis_control_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ /* status endpoint is optional; this could be patched later */
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+ .bLength = sizeof header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+
+ .bcdCDC = __constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
+ .bLength = sizeof call_mgmt_descriptor,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
+
+ .bmCapabilities = 0x00,
+ .bDataInterface = 0x01,
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+ .bLength = sizeof acm_descriptor,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
+
+ .bmCapabilities = 0x00,
+};
+
+static struct usb_cdc_union_desc rndis_union_desc __initdata = {
+ .bLength = sizeof(rndis_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
+/* the data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor rndis_data_intf __initdata = {
+ .bLength = sizeof rndis_data_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+ /* control interface matches ACM, not Ethernet */
+ (struct usb_descriptor_header *) &rndis_control_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &acm_descriptor,
+ (struct usb_descriptor_header *) &rndis_union_desc,
+ (struct usb_descriptor_header *) &fs_notify_desc,
+ /* data interface has no altsetting */
+ (struct usb_descriptor_header *) &rndis_data_intf,
+ (struct usb_descriptor_header *) &fs_in_desc,
+ (struct usb_descriptor_header *) &fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
+ .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+ /* control interface matches ACM, not Ethernet */
+ (struct usb_descriptor_header *) &rndis_control_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &acm_descriptor,
+ (struct usb_descriptor_header *) &rndis_union_desc,
+ (struct usb_descriptor_header *) &hs_notify_desc,
+ /* data interface has no altsetting */
+ (struct usb_descriptor_header *) &rndis_data_intf,
+ (struct usb_descriptor_header *) &hs_in_desc,
+ (struct usb_descriptor_header *) &hs_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string rndis_string_defs[] = {
+ [0].s = "RNDIS Communications Control",
+ [1].s = "RNDIS Ethernet Data",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings rndis_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = rndis_string_defs,
+};
+
+static struct usb_gadget_strings *rndis_strings[] = {
+ &rndis_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct sk_buff *rndis_add_header(struct sk_buff *skb)
+{
+ skb = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
+ if (skb)
+ rndis_add_hdr(skb);
+ return skb;
+}
+
+static void rndis_response_available(void *_rndis)
+{
+ struct f_rndis *rndis = _rndis;
+ struct usb_request *req = rndis->notify_req;
+ struct usb_composite_dev *cdev = rndis->port.func.config->cdev;
+ __le32 *data = req->buf;
+ int status;
+
+ if (atomic_inc_return(&rndis->notify_count))
+ return;
+
+ /* Send RNDIS RESPONSE_AVAILABLE notification; a
+ * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too
+ *
+ * This is the only notification defined by RNDIS.
+ */
+ data[0] = cpu_to_le32(1);
+ data[1] = cpu_to_le32(0);
+
+ status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+ if (status) {
+ atomic_dec(&rndis->notify_count);
+ DBG(cdev, "notify/0 --> %d\n", status);
+ }
+}
+
+static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_rndis *rndis = req->context;
+ struct usb_composite_dev *cdev = rndis->port.func.config->cdev;
+ int status = req->status;
+
+ /* after TX:
+ * - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
+ * - RNDIS_RESPONSE_AVAILABLE (status/irq)
+ */
+ switch (status) {
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ /* connection gone */
+ atomic_set(&rndis->notify_count, 0);
+ break;
+ default:
+ DBG(cdev, "RNDIS %s response error %d, %d/%d\n",
+ ep->name, status,
+ req->actual, req->length);
+ /* FALLTHROUGH */
+ case 0:
+ if (ep != rndis->notify)
+ break;
+
+ /* handle multiple pending RNDIS_RESPONSE_AVAILABLE
+ * notifications by resending until we're done
+ */
+ if (atomic_dec_and_test(&rndis->notify_count))
+ break;
+ status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+ if (status) {
+ atomic_dec(&rndis->notify_count);
+ DBG(cdev, "notify/1 --> %d\n", status);
+ }
+ break;
+ }
+}
+
+static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_rndis *rndis = req->context;
+ struct usb_composite_dev *cdev = rndis->port.func.config->cdev;
+ int status;
+
+ /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
+// spin_lock(&dev->lock);
+ status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
+ if (status < 0)
+ ERROR(cdev, "RNDIS command error %d, %d/%d\n",
+ status, req->actual, req->length);
+// spin_unlock(&dev->lock);
+}
+
+static int
+rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_rndis *rndis = func_to_rndis(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything except
+ * CDC class messages; interface activation uses set_alt().
+ */
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+ /* RNDIS uses the CDC command encapsulation mechanism to implement
+ * an RPC scheme, with much getting/setting of attributes by OID.
+ */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+ if (w_length > req->length || w_value
+ || w_index != rndis->ctrl_id)
+ goto invalid;
+ /* read the request; process it later */
+ value = w_length;
+ req->complete = rndis_command_complete;
+ req->context = rndis;
+ /* later, rndis_response_available() sends a notification */
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_ENCAPSULATED_RESPONSE:
+ if (w_value || w_index != rndis->ctrl_id)
+ goto invalid;
+ else {
+ u8 *buf;
+ u32 n;
+
+ /* return the result */
+ buf = rndis_get_next_response(rndis->config, &n);
+ if (buf) {
+ memcpy(req->buf, buf, n);
+ req->complete = rndis_response_complete;
+ rndis_free_response(rndis->config, buf);
+ value = n;
+ }
+ /* else stalls ... spec says to avoid that */
+ }
+ break;
+
+ default:
+invalid:
+ VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "rndis response on err %d\n", value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+
+static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_rndis *rndis = func_to_rndis(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt == 0 */
+
+ if (intf == rndis->ctrl_id) {
+ if (rndis->notify->driver_data) {
+ VDBG(cdev, "reset rndis control %d\n", intf);
+ usb_ep_disable(rndis->notify);
+ } else {
+ VDBG(cdev, "init rndis ctrl %d\n", intf);
+ rndis->notify_desc = ep_choose(cdev->gadget,
+ rndis->hs.notify,
+ rndis->fs.notify);
+ }
+ usb_ep_enable(rndis->notify, rndis->notify_desc);
+ rndis->notify->driver_data = rndis;
+
+ } else if (intf == rndis->data_id) {
+ struct net_device *net;
+
+ if (rndis->port.in_ep->driver_data) {
+ DBG(cdev, "reset rndis\n");
+ gether_disconnect(&rndis->port);
+ } else {
+ DBG(cdev, "init rndis\n");
+ rndis->port.in = ep_choose(cdev->gadget,
+ rndis->hs.in, rndis->fs.in);
+ rndis->port.out = ep_choose(cdev->gadget,
+ rndis->hs.out, rndis->fs.out);
+ }
+
+ /* Avoid ZLPs; they can be troublesome. */
+ rndis->port.is_zlp_ok = false;
+
+ /* RNDIS should be in the "RNDIS uninitialized" state,
+ * either never activated or after rndis_uninit().
+ *
+ * We don't want data to flow here until a nonzero packet
+ * filter is set, at which point it enters "RNDIS data
+ * initialized" state ... but we do want the endpoints
+ * to be activated. It's a strange little state.
+ *
+ * REVISIT the RNDIS gadget code has done this wrong for a
+ * very long time. We need another call to the link layer
+ * code -- gether_updown(...bool) maybe -- to do it right.
+ */
+ rndis->port.cdc_filter = 0;
+
+ DBG(cdev, "RNDIS RX/TX early activation ... \n");
+ net = gether_connect(&rndis->port);
+ if (IS_ERR(net))
+ return PTR_ERR(net);
+
+ rndis_set_param_dev(rndis->config, net,
+ &rndis->port.cdc_filter);
+ } else
+ goto fail;
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static void rndis_disable(struct usb_function *f)
+{
+ struct f_rndis *rndis = func_to_rndis(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ if (!rndis->notify->driver_data)
+ return;
+
+ DBG(cdev, "rndis deactivated\n");
+
+ rndis_uninit(rndis->config);
+ gether_disconnect(&rndis->port);
+
+ usb_ep_disable(rndis->notify);
+ rndis->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * This isn't quite the same mechanism as CDC Ethernet, since the
+ * notification scheme passes less data, but the same set of link
+ * states must be tested. A key difference is that altsettings are
+ * not used to tell whether the link should send packets or not.
+ */
+
+static void rndis_open(struct gether *geth)
+{
+ struct f_rndis *rndis = func_to_rndis(&geth->func);
+ struct usb_composite_dev *cdev = geth->func.config->cdev;
+
+ DBG(cdev, "%s\n", __func__);
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3,
+ bitrate(cdev->gadget) / 100);
+ rndis_signal_connect(rndis->config);
+}
+
+static void rndis_close(struct gether *geth)
+{
+ struct f_rndis *rndis = func_to_rndis(&geth->func);
+
+ DBG(geth->func.config->cdev, "%s\n", __func__);
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+ rndis_signal_disconnect(rndis->config);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+rndis_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_rndis *rndis = func_to_rndis(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ rndis->ctrl_id = status;
+
+ rndis_control_intf.bInterfaceNumber = status;
+ rndis_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ rndis->data_id = status;
+
+ rndis_data_intf.bInterfaceNumber = status;
+ rndis_union_desc.bSlaveInterface0 = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+ if (!ep)
+ goto fail;
+ rndis->port.in_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+ if (!ep)
+ goto fail;
+ rndis->port.out_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* NOTE: a status/notification endpoint is, strictly speaking,
+ * optional. We don't treat it that way though! It's simpler,
+ * and some newer profiles don't treat it as optional.
+ */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+ if (!ep)
+ goto fail;
+ rndis->notify = ep;
+ ep->driver_data = cdev; /* claim */
+
+ status = -ENOMEM;
+
+ /* allocate notification request and buffer */
+ rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+ if (!rndis->notify_req)
+ goto fail;
+ rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+ if (!rndis->notify_req->buf)
+ goto fail;
+ rndis->notify_req->length = STATUS_BYTECOUNT;
+ rndis->notify_req->context = rndis;
+ rndis->notify_req->complete = rndis_response_complete;
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(eth_fs_function);
+ if (!f->descriptors)
+ goto fail;
+
+ rndis->fs.in = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_in_desc);
+ rndis->fs.out = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_out_desc);
+ rndis->fs.notify = usb_find_endpoint(eth_fs_function,
+ f->descriptors, &fs_notify_desc);
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_in_desc.bEndpointAddress =
+ fs_in_desc.bEndpointAddress;
+ hs_out_desc.bEndpointAddress =
+ fs_out_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+
+ if (!f->hs_descriptors)
+ goto fail;
+
+ rndis->hs.in = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_in_desc);
+ rndis->hs.out = usb_find_endpoint(eth_hs_function,
+ f->hs_descriptors, &hs_out_desc);
+ }
+
+ rndis->port.open = rndis_open;
+ rndis->port.close = rndis_close;
+
+ status = rndis_register(rndis_response_available, rndis);
+ if (status < 0)
+ goto fail;
+ rndis->config = status;
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+ rndis_set_host_mac(rndis->config, rndis->ethaddr);
+
+#if 0
+// FIXME
+ if (rndis_set_param_vendor(rndis->config, vendorID,
+ manufacturer))
+ goto fail0;
+#endif
+
+ /* NOTE: all that is done without knowing or caring about
+ * the network link ... which is unavailable to this code
+ * until we're activated via set_alt().
+ */
+
+ DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ rndis->port.in_ep->name, rndis->port.out_ep->name,
+ rndis->notify->name);
+ return 0;
+
+fail:
+ if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
+ if (rndis->notify_req) {
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+ }
+
+ /* we might as well release our claims on endpoints */
+ if (rndis->notify)
+ rndis->notify->driver_data = NULL;
+ if (rndis->port.out)
+ rndis->port.out_ep->driver_data = NULL;
+ if (rndis->port.in)
+ rndis->port.in_ep->driver_data = NULL;
+
+ ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+ return status;
+}
+
+static void
+rndis_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_rndis *rndis = func_to_rndis(f);
+
+ rndis_deregister(rndis->config);
+ rndis_exit();
+
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+
+ kfree(rndis);
+}
+
+/* Some controllers can't support RNDIS ... */
+static inline bool can_support_rndis(struct usb_configuration *c)
+{
+ /* only two endpoints on sa1100 */
+ if (gadget_is_sa1100(c->cdev->gadget))
+ return false;
+
+ /* everything else is *presumably* fine */
+ return true;
+}
+
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+ struct f_rndis *rndis;
+ int status;
+
+ if (!can_support_rndis(c) || !ethaddr)
+ return -EINVAL;
+
+ /* maybe allocate device-global string IDs */
+ if (rndis_string_defs[0].id == 0) {
+
+ /* ... and setup RNDIS itself */
+ status = rndis_init();
+ if (status < 0)
+ return status;
+
+ /* control interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ rndis_string_defs[0].id = status;
+ rndis_control_intf.iInterface = status;
+
+ /* data interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ rndis_string_defs[1].id = status;
+ rndis_data_intf.iInterface = status;
+ }
+
+ /* allocate and initialize one new instance */
+ status = -ENOMEM;
+ rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
+ if (!rndis)
+ goto fail;
+
+ memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+
+ /* RNDIS activates when the host changes this filter */
+ rndis->port.cdc_filter = 0;
+
+ /* RNDIS has special (and complex) framing */
+ rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
+ rndis->port.wrap = rndis_add_header;
+ rndis->port.unwrap = rndis_rm_hdr;
+
+ rndis->port.func.name = "rndis";
+ rndis->port.func.strings = rndis_strings;
+ /* descriptors are per-instance copies */
+ rndis->port.func.bind = rndis_bind;
+ rndis->port.func.unbind = rndis_unbind;
+ rndis->port.func.set_alt = rndis_set_alt;
+ rndis->port.func.setup = rndis_setup;
+ rndis->port.func.disable = rndis_disable;
+
+ status = usb_add_function(c, &rndis->port.func);
+ if (status) {
+ kfree(rndis);
+fail:
+ rndis_exit();
+ }
+ return status;
+}
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
new file mode 100644
index 00000000000..1b6bde9aaed
--- /dev/null
+++ b/drivers/usb/gadget/f_serial.c
@@ -0,0 +1,296 @@
+/*
+ * f_serial.c - generic USB serial function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This function packages a simple "generic serial" port with no real
+ * control mechanisms, just raw data transfer over two bulk endpoints.
+ *
+ * Because it's not standardized, this isn't as interoperable as the
+ * CDC ACM driver. However, for many purposes it's just as functional
+ * if you can arrange appropriate host side drivers.
+ */
+
+struct gser_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+};
+
+struct f_gser {
+ struct gserial port;
+ u8 data_id;
+ u8 port_num;
+
+ struct usb_descriptor_header **fs_function;
+ struct gser_descs fs;
+ struct usb_descriptor_header **hs_function;
+ struct gser_descs hs;
+};
+
+static inline struct f_gser *func_to_gser(struct usb_function *f)
+{
+ return container_of(f, struct f_gser, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor gser_interface_desc __initdata = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ /* .bInterfaceNumber = DYNAMIC */
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+ (struct usb_descriptor_header *) &gser_interface_desc,
+ (struct usb_descriptor_header *) &gser_fs_in_desc,
+ (struct usb_descriptor_header *) &gser_fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+ (struct usb_descriptor_header *) &gser_interface_desc,
+ (struct usb_descriptor_header *) &gser_hs_in_desc,
+ (struct usb_descriptor_header *) &gser_hs_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string gser_string_defs[] = {
+ [0].s = "Generic Serial",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings gser_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = gser_string_defs,
+};
+
+static struct usb_gadget_strings *gser_strings[] = {
+ &gser_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_gser *gser = func_to_gser(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt == 0, so this is an activation or a reset */
+
+ if (gser->port.in->driver_data) {
+ DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
+ gserial_disconnect(&gser->port);
+ } else {
+ DBG(cdev, "activate generic ttyGS%d\n", gser->port_num);
+ gser->port.in_desc = ep_choose(cdev->gadget,
+ gser->hs.in, gser->fs.in);
+ gser->port.out_desc = ep_choose(cdev->gadget,
+ gser->hs.out, gser->fs.out);
+ }
+ gserial_connect(&gser->port, gser->port_num);
+ return 0;
+}
+
+static void gser_disable(struct usb_function *f)
+{
+ struct f_gser *gser = func_to_gser(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
+ gserial_disconnect(&gser->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+gser_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_gser *gser = func_to_gser(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ gser->data_id = status;
+ gser_interface_desc.bInterfaceNumber = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc);
+ if (!ep)
+ goto fail;
+ gser->port.in = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
+ if (!ep)
+ goto fail;
+ gser->port.out = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(gser_fs_function);
+
+ gser->fs.in = usb_find_endpoint(gser_fs_function,
+ f->descriptors, &gser_fs_in_desc);
+ gser->fs.out = usb_find_endpoint(gser_fs_function,
+ f->descriptors, &gser_fs_out_desc);
+
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ gser_hs_in_desc.bEndpointAddress =
+ gser_fs_in_desc.bEndpointAddress;
+ gser_hs_out_desc.bEndpointAddress =
+ gser_fs_out_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
+
+ gser->hs.in = usb_find_endpoint(gser_hs_function,
+ f->hs_descriptors, &gser_hs_in_desc);
+ gser->hs.out = usb_find_endpoint(gser_hs_function,
+ f->hs_descriptors, &gser_hs_out_desc);
+ }
+
+ DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
+ gser->port_num,
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ gser->port.in->name, gser->port.out->name);
+ return 0;
+
+fail:
+ /* we might as well release our claims on endpoints */
+ if (gser->port.out)
+ gser->port.out->driver_data = NULL;
+ if (gser->port.in)
+ gser->port.in->driver_data = NULL;
+
+ ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+ return status;
+}
+
+static void
+gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+ kfree(func_to_gser(f));
+}
+
+/**
+ * gser_bind_config - add a generic serial function to a configuration
+ * @c: the configuration to support the serial instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds. Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+{
+ struct f_gser *gser;
+ int status;
+
+ /* REVISIT might want instance-specific strings to help
+ * distinguish instances ...
+ */
+
+ /* maybe allocate device-global string ID */
+ if (gser_string_defs[0].id == 0) {
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ gser_string_defs[0].id = status;
+ }
+
+ /* allocate and initialize one new instance */
+ gser = kzalloc(sizeof *gser, GFP_KERNEL);
+ if (!gser)
+ return -ENOMEM;
+
+ gser->port_num = port_num;
+
+ gser->port.func.name = "gser";
+ gser->port.func.strings = gser_strings;
+ gser->port.func.bind = gser_bind;
+ gser->port.func.unbind = gser_unbind;
+ gser->port.func.set_alt = gser_set_alt;
+ gser->port.func.disable = gser_disable;
+
+ status = usb_add_function(c, &gser->port.func);
+ if (status)
+ kfree(gser);
+ return status;
+}
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
new file mode 100644
index 00000000000..f18c3a14d72
--- /dev/null
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -0,0 +1,587 @@
+/*
+ * f_sourcesink.c - USB peripheral source/sink configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
+ * controller drivers.
+ *
+ * This just sinks bulk packets OUT to the peripheral and sources them IN
+ * to the host, optionally with specific data patterns for integrity tests.
+ * As such it supports basic functionality and load tests.
+ *
+ * In terms of control messaging, this supports all the standard requests
+ * plus two that support control-OUT tests. If the optional "autoresume"
+ * mode is enabled, it provides good functional coverage for the "USBCV"
+ * test harness from USB-IF.
+ *
+ * Note that because this doesn't queue more than one request at a time,
+ * some other function must be used to test queueing logic. The network
+ * link (g_ether) is the best overall option for that, since its TX and RX
+ * queues are relatively independent, will receive a range of packet sizes,
+ * and can often be made to run out completely. Those issues are important
+ * when stress testing peripheral controller drivers.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices. However, it
+ * can be combined with other independent configurations.
+ */
+struct f_sourcesink {
+ struct usb_function function;
+
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep;
+ struct timer_list resume;
+};
+
+static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
+{
+ return container_of(f, struct f_sourcesink, function);
+}
+
+static unsigned autoresume;
+module_param(autoresume, uint, 0);
+MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
+
+static unsigned pattern;
+module_param(pattern, uint, 0);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor source_sink_intf = {
+ .bLength = sizeof source_sink_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_source_sink_descs[] = {
+ (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &fs_sink_desc,
+ (struct usb_descriptor_header *) &fs_source_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_source_sink_descs[] = {
+ (struct usb_descriptor_header *) &source_sink_intf,
+ (struct usb_descriptor_header *) &hs_source_desc,
+ (struct usb_descriptor_header *) &hs_sink_desc,
+ NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_sourcesink[] = {
+ [0].s = "source and sink data",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_sourcesink = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_sourcesink,
+};
+
+static struct usb_gadget_strings *sourcesink_strings[] = {
+ &stringtab_sourcesink,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void sourcesink_autoresume(unsigned long _c)
+{
+ struct usb_composite_dev *cdev = (void *)_c;
+ struct usb_gadget *g = cdev->gadget;
+
+ /* Normally the host would be woken up for something
+ * more significant than just a timer firing; likely
+ * because of some direct user request.
+ */
+ if (g->speed != USB_SPEED_UNKNOWN) {
+ int status = usb_gadget_wakeup(g);
+ DBG(cdev, "%s --> %d\n", __func__, status);
+ }
+}
+
+static int __init
+sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_sourcesink *ss = func_to_ss(f);
+ int id;
+
+ /* allocate interface ID(s) */
+ id = usb_interface_id(c, f);
+ if (id < 0)
+ return id;
+ source_sink_intf.bInterfaceNumber = id;
+
+ /* allocate endpoints */
+ ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+ if (!ss->in_ep) {
+autoconf_fail:
+ ERROR(cdev, "%s: can't autoconfigure on %s\n",
+ f->name, cdev->gadget->name);
+ return -ENODEV;
+ }
+ ss->in_ep->driver_data = cdev; /* claim */
+
+ ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+ if (!ss->out_ep)
+ goto autoconf_fail;
+ ss->out_ep->driver_data = cdev; /* claim */
+
+ setup_timer(&ss->resume, sourcesink_autoresume,
+ (unsigned long) c->cdev);
+
+ /* support high speed hardware */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_source_desc.bEndpointAddress =
+ fs_source_desc.bEndpointAddress;
+ hs_sink_desc.bEndpointAddress =
+ fs_sink_desc.bEndpointAddress;
+ f->hs_descriptors = hs_source_sink_descs;
+ }
+
+ DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ f->name, ss->in_ep->name, ss->out_ep->name);
+ return 0;
+}
+
+static void
+sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ kfree(func_to_ss(f));
+}
+
+/* optionally require specific source/sink data patterns */
+static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
+{
+ unsigned i;
+ u8 *buf = req->buf;
+ struct usb_composite_dev *cdev = ss->function.config->cdev;
+
+ for (i = 0; i < req->actual; i++, buf++) {
+ switch (pattern) {
+
+ /* all-zeroes has no synchronization issues */
+ case 0:
+ if (*buf == 0)
+ continue;
+ break;
+
+ /* "mod63" stays in sync with short-terminated transfers,
+ * OR otherwise when host and gadget agree on how large
+ * each usb transfer request should be. Resync is done
+ * with set_interface or set_config. (We *WANT* it to
+ * get quickly out of sync if controllers or their drivers
+ * stutter for any reason, including buffer duplcation...)
+ */
+ case 1:
+ if (*buf == (u8)(i % 63))
+ continue;
+ break;
+ }
+ ERROR(cdev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
+ usb_ep_set_halt(ss->out_ep);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+{
+ unsigned i;
+ u8 *buf = req->buf;
+
+ switch (pattern) {
+ case 0:
+ memset(req->buf, 0, req->length);
+ break;
+ case 1:
+ for (i = 0; i < req->length; i++)
+ *buf++ = (u8) (i % 63);
+ break;
+ }
+}
+
+static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_sourcesink *ss = ep->driver_data;
+ struct usb_composite_dev *cdev = ss->function.config->cdev;
+ int status = req->status;
+
+ switch (status) {
+
+ case 0: /* normal completion? */
+ if (ep == ss->out_ep) {
+ check_read_data(ss, req);
+ memset(req->buf, 0x55, req->length);
+ } else
+ reinit_write_data(ep, req);
+ break;
+
+ /* this endpoint is normally active while we're configured */
+ case -ECONNABORTED: /* hardware forced ep reset */
+ case -ECONNRESET: /* request dequeued */
+ case -ESHUTDOWN: /* disconnect from host */
+ VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
+ req->actual, req->length);
+ if (ep == ss->out_ep)
+ check_read_data(ss, req);
+ free_ep_req(ep, req);
+ return;
+
+ case -EOVERFLOW: /* buffer overrun on read means that
+ * we didn't provide a big enough
+ * buffer.
+ */
+ default:
+#if 1
+ DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
+ status, req->actual, req->length);
+#endif
+ case -EREMOTEIO: /* short read */
+ break;
+ }
+
+ status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (status) {
+ ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n",
+ ep->name, req->length, status);
+ usb_ep_set_halt(ep);
+ /* FIXME recover later ... somehow */
+ }
+}
+
+static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in)
+{
+ struct usb_ep *ep;
+ struct usb_request *req;
+ int status;
+
+ ep = is_in ? ss->in_ep : ss->out_ep;
+ req = alloc_ep_req(ep);
+ if (!req)
+ return -ENOMEM;
+
+ req->complete = source_sink_complete;
+ if (is_in)
+ reinit_write_data(ep, req);
+ else
+ memset(req->buf, 0x55, req->length);
+
+ status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (status) {
+ struct usb_composite_dev *cdev;
+
+ cdev = ss->function.config->cdev;
+ ERROR(cdev, "start %s %s --> %d\n",
+ is_in ? "IN" : "OUT",
+ ep->name, status);
+ free_ep_req(ep, req);
+ }
+
+ return status;
+}
+
+static void disable_source_sink(struct f_sourcesink *ss)
+{
+ struct usb_composite_dev *cdev;
+
+ cdev = ss->function.config->cdev;
+ disable_endpoints(cdev, ss->in_ep, ss->out_ep);
+ del_timer(&ss->resume);
+ VDBG(cdev, "%s disabled\n", ss->function.name);
+}
+
+static int
+enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
+{
+ int result = 0;
+ const struct usb_endpoint_descriptor *src, *sink;
+ struct usb_ep *ep;
+
+ src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+ sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+ /* one endpoint writes (sources) zeroes IN (to the host) */
+ ep = ss->in_ep;
+ result = usb_ep_enable(ep, src);
+ if (result < 0)
+ return result;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, true);
+ if (result < 0) {
+fail:
+ ep = ss->in_ep;
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ return result;
+ }
+
+ /* one endpoint reads (sinks) anything OUT (from the host) */
+ ep = ss->out_ep;
+ result = usb_ep_enable(ep, sink);
+ if (result < 0)
+ goto fail;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, false);
+ if (result < 0) {
+ usb_ep_disable(ep);
+ ep->driver_data = NULL;
+ goto fail;
+ }
+
+ DBG(cdev, "%s enabled\n", ss->function.name);
+ return result;
+}
+
+static int sourcesink_set_alt(struct usb_function *f,
+ unsigned intf, unsigned alt)
+{
+ struct f_sourcesink *ss = func_to_ss(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt is zero */
+ if (ss->in_ep->driver_data)
+ disable_source_sink(ss);
+ return enable_source_sink(cdev, ss);
+}
+
+static void sourcesink_disable(struct usb_function *f)
+{
+ struct f_sourcesink *ss = func_to_ss(f);
+
+ disable_source_sink(ss);
+}
+
+static void sourcesink_suspend(struct usb_function *f)
+{
+ struct f_sourcesink *ss = func_to_ss(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
+ return;
+
+ if (autoresume) {
+ mod_timer(&ss->resume, jiffies + (HZ * autoresume));
+ DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
+ } else
+ DBG(cdev, "%s\n", __func__);
+}
+
+static void sourcesink_resume(struct usb_function *f)
+{
+ struct f_sourcesink *ss = func_to_ss(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "%s\n", __func__);
+ del_timer(&ss->resume);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init sourcesink_bind_config(struct usb_configuration *c)
+{
+ struct f_sourcesink *ss;
+ int status;
+
+ ss = kzalloc(sizeof *ss, GFP_KERNEL);
+ if (!ss)
+ return -ENOMEM;
+
+ ss->function.name = "source/sink";
+ ss->function.descriptors = fs_source_sink_descs;
+ ss->function.bind = sourcesink_bind;
+ ss->function.unbind = sourcesink_unbind;
+ ss->function.set_alt = sourcesink_set_alt;
+ ss->function.disable = sourcesink_disable;
+ ss->function.suspend = sourcesink_suspend;
+ ss->function.resume = sourcesink_resume;
+
+ status = usb_add_function(c, &ss->function);
+ if (status)
+ kfree(ss);
+ return status;
+}
+
+static int sourcesink_setup(struct usb_configuration *c,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_request *req = c->cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything except
+ * the two control test requests.
+ */
+ switch (ctrl->bRequest) {
+
+ /*
+ * These are the same vendor-specific requests supported by
+ * Intel's USB 2.0 compliance test devices. We exceed that
+ * device spec by allowing multiple-packet requests.
+ *
+ * NOTE: the Control-OUT data stays in req->buf ... better
+ * would be copying it into a scratch buffer, so that other
+ * requests may safely intervene.
+ */
+ case 0x5b: /* control WRITE test -- fill the buffer */
+ if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
+ goto unknown;
+ if (w_value || w_index)
+ break;
+ /* just read that many bytes into the buffer */
+ if (w_length > req->length)
+ break;
+ value = w_length;
+ break;
+ case 0x5c: /* control READ test -- return the buffer */
+ if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
+ goto unknown;
+ if (w_value || w_index)
+ break;
+ /* expect those bytes are still in the buffer; send back */
+ if (w_length > req->length)
+ break;
+ value = w_length;
+ break;
+
+ default:
+unknown:
+ VDBG(c->cdev,
+ "unknown control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(c->cdev, "source/sinkc response, err %d\n",
+ value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static struct usb_configuration sourcesink_driver = {
+ .label = "source/sink",
+ .strings = sourcesink_strings,
+ .bind = sourcesink_bind_config,
+ .setup = sourcesink_setup,
+ .bConfigurationValue = 3,
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
+ /* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * sourcesink_add - add a source/sink testing configuration to a device
+ * @cdev: the device to support the configuration
+ */
+int __init sourcesink_add(struct usb_composite_dev *cdev)
+{
+ int id;
+
+ /* allocate string ID(s) */
+ id = usb_string_id(cdev);
+ if (id < 0)
+ return id;
+ strings_sourcesink[0].id = id;
+
+ source_sink_intf.iInterface = id;
+ sourcesink_driver.iConfiguration = id;
+
+ /* support autoresume for remote wakeup testing */
+ if (autoresume)
+ sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+
+ /* support OTG systems */
+ if (gadget_is_otg(cdev->gadget)) {
+ sourcesink_driver.descriptors = otg_desc;
+ sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ }
+
+ return usb_add_config(cdev, &sourcesink_driver);
+}
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
new file mode 100644
index 00000000000..afeab9a0523
--- /dev/null
+++ b/drivers/usb/gadget/f_subset.c
@@ -0,0 +1,423 @@
+/*
+ * f_subset.c -- "CDC Subset" Ethernet link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function packages a simple "CDC Subset" Ethernet port with no real
+ * control mechanisms; just raw data transfer over two bulk endpoints.
+ * The data transfer model is exactly that of CDC Ethernet, which is
+ * why we call it the "CDC Subset".
+ *
+ * Because it's not standardized, this has some interoperability issues.
+ * They mostly relate to driver binding, since the data transfer model is
+ * so simple (CDC Ethernet). The original versions of this protocol used
+ * specific product/vendor IDs: byteswapped IDs for Digital Equipment's
+ * SA-1100 "Itsy" board, which could run Linux 2.4 kernels and supported
+ * daughtercards with USB peripheral connectors. (It was used more often
+ * with other boards, using the Itsy identifiers.) Linux hosts recognized
+ * this with CONFIG_USB_ARMLINUX; these devices have only one configuration
+ * and one interface.
+ *
+ * At some point, MCCI defined a (nonconformant) CDC MDLM variant called
+ * "SAFE", which happens to have a mode which is identical to the "CDC
+ * Subset" in terms of data transfer and lack of control model. This was
+ * adopted by later Sharp Zaurus models, and by some other software which
+ * Linux hosts recognize with CONFIG_USB_NET_ZAURUS.
+ *
+ * Because Microsoft's RNDIS drivers are far from robust, we added a few
+ * descriptors to the CDC Subset code, making this code look like a SAFE
+ * implementation. This lets you use MCCI's host side MS-Windows drivers
+ * if you get fed up with RNDIS. It also makes it easier for composite
+ * drivers to work, since they can use class based binding instead of
+ * caring about specific product and vendor IDs.
+ */
+
+struct geth_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+};
+
+struct f_gether {
+ struct gether port;
+
+ char ethaddr[14];
+
+ struct usb_descriptor_header **fs_function;
+ struct geth_descs fs;
+ struct usb_descriptor_header **hs_function;
+ struct geth_descs hs;
+};
+
+static inline struct f_gether *func_to_geth(struct usb_function *f)
+{
+ return container_of(f, struct f_gether, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * "Simple" CDC-subset option is a simple vendor-neutral model that most
+ * full speed controllers can handle: one interface, two bulk endpoints.
+ * To assist host side drivers, we fancy it up a bit, and add descriptors so
+ * some host side drivers will understand it as a "SAFE" variant.
+ *
+ * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various ways.
+ * Data endpoints live in the control interface, there's no data interface.
+ * And it's not used to talk to a cell phone radio.
+ */
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor subset_data_intf __initdata = {
+ .bLength = sizeof subset_data_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+ .bLength = sizeof header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+
+ .bcdCDC = __constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+ .bLength = sizeof mdlm_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_MDLM_TYPE,
+
+ .bcdVersion = __constant_cpu_to_le16(0x0100),
+ .bGUID = {
+ 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+ 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+ },
+};
+
+/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
+ * can't really use its struct. All we do here is say that we're using
+ * the submode of "SAFE" which directly matches the CDC Subset.
+ */
+static u8 mdlm_detail_desc[] __initdata = {
+ 6,
+ USB_DT_CS_INTERFACE,
+ USB_CDC_MDLM_DETAIL_TYPE,
+
+ 0, /* "SAFE" */
+ 0, /* network control capabilities (none) */
+ 0, /* network data capabilities ("raw" encapsulation) */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+ .bLength = sizeof ether_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
+
+ /* this descriptor actually adds value, surprise! */
+ /* .iMACAddress = DYNAMIC */
+ .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */
+ .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN),
+ .wNumberMCFilters = __constant_cpu_to_le16(0),
+ .bNumberPowerFilters = 0,
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+ (struct usb_descriptor_header *) &subset_data_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &mdlm_desc,
+ (struct usb_descriptor_header *) &mdlm_detail_desc,
+ (struct usb_descriptor_header *) &ether_desc,
+ (struct usb_descriptor_header *) &fs_in_desc,
+ (struct usb_descriptor_header *) &fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+ (struct usb_descriptor_header *) &subset_data_intf,
+ (struct usb_descriptor_header *) &header_desc,
+ (struct usb_descriptor_header *) &mdlm_desc,
+ (struct usb_descriptor_header *) &mdlm_detail_desc,
+ (struct usb_descriptor_header *) &ether_desc,
+ (struct usb_descriptor_header *) &hs_in_desc,
+ (struct usb_descriptor_header *) &hs_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string geth_string_defs[] = {
+ [0].s = "CDC Ethernet Subset/SAFE",
+ [1].s = NULL /* DYNAMIC */,
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings geth_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = geth_string_defs,
+};
+
+static struct usb_gadget_strings *geth_strings[] = {
+ &geth_string_table,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_gether *geth = func_to_geth(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct net_device *net;
+
+ /* we know alt == 0, so this is an activation or a reset */
+
+ if (geth->port.in_ep->driver_data) {
+ DBG(cdev, "reset cdc subset\n");
+ gether_disconnect(&geth->port);
+ }
+
+ DBG(cdev, "init + activate cdc subset\n");
+ geth->port.in = ep_choose(cdev->gadget,
+ geth->hs.in, geth->fs.in);
+ geth->port.out = ep_choose(cdev->gadget,
+ geth->hs.out, geth->fs.out);
+
+ net = gether_connect(&geth->port);
+ return IS_ERR(net) ? PTR_ERR(net) : 0;
+}
+
+static void geth_disable(struct usb_function *f)
+{
+ struct f_gether *geth = func_to_geth(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ DBG(cdev, "net deactivated\n");
+ gether_disconnect(&geth->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+geth_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_gether *geth = func_to_geth(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ subset_data_intf.bInterfaceNumber = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+ if (!ep)
+ goto fail;
+ geth->port.in_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+ if (!ep)
+ goto fail;
+ geth->port.out_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(fs_eth_function);
+
+ geth->fs.in = usb_find_endpoint(fs_eth_function,
+ f->descriptors, &fs_in_desc);
+ geth->fs.out = usb_find_endpoint(fs_eth_function,
+ f->descriptors, &fs_out_desc);
+
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_in_desc.bEndpointAddress =
+ fs_in_desc.bEndpointAddress;
+ hs_out_desc.bEndpointAddress =
+ fs_out_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
+
+ geth->hs.in = usb_find_endpoint(hs_eth_function,
+ f->hs_descriptors, &hs_in_desc);
+ geth->hs.out = usb_find_endpoint(hs_eth_function,
+ f->hs_descriptors, &hs_out_desc);
+ }
+
+ /* NOTE: all that is done without knowing or caring about
+ * the network link ... which is unavailable to this code
+ * until we're activated via set_alt().
+ */
+
+ DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n",
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ geth->port.in_ep->name, geth->port.out_ep->name);
+ return 0;
+
+fail:
+ /* we might as well release our claims on endpoints */
+ if (geth->port.out)
+ geth->port.out_ep->driver_data = NULL;
+ if (geth->port.in)
+ geth->port.in_ep->driver_data = NULL;
+
+ ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+ return status;
+}
+
+static void
+geth_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+ geth_string_defs[1].s = NULL;
+ kfree(func_to_geth(f));
+}
+
+/**
+ * geth_bind_config - add CDC Subset network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+ struct f_gether *geth;
+ int status;
+
+ if (!ethaddr)
+ return -EINVAL;
+
+ /* maybe allocate device-global string IDs */
+ if (geth_string_defs[0].id == 0) {
+
+ /* interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ geth_string_defs[0].id = status;
+ subset_data_intf.iInterface = status;
+
+ /* MAC address */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ geth_string_defs[1].id = status;
+ ether_desc.iMACAddress = status;
+ }
+
+ /* allocate and initialize one new instance */
+ geth = kzalloc(sizeof *geth, GFP_KERNEL);
+ if (!geth)
+ return -ENOMEM;
+
+ /* export host's Ethernet address in CDC format */
+ snprintf(geth->ethaddr, sizeof geth->ethaddr,
+ "%02X%02X%02X%02X%02X%02X",
+ ethaddr[0], ethaddr[1], ethaddr[2],
+ ethaddr[3], ethaddr[4], ethaddr[5]);
+ geth_string_defs[1].s = geth->ethaddr;
+
+ geth->port.cdc_filter = DEFAULT_FILTER;
+
+ geth->port.func.name = "cdc_subset";
+ geth->port.func.strings = geth_strings;
+ geth->port.func.bind = geth_bind;
+ geth->port.func.unbind = geth_unbind;
+ geth->port.func.set_alt = geth_set_alt;
+ geth->port.func.disable = geth_disable;
+
+ status = usb_add_function(c, &geth->port.func);
+ if (status) {
+ geth_string_defs[1].s = NULL;
+ kfree(geth);
+ }
+ return status;
+}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 47bb9f09a1a..15c24edbb61 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3867,8 +3867,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
curlun->dev.parent = &gadget->dev;
curlun->dev.driver = &fsg_driver.driver;
dev_set_drvdata(&curlun->dev, fsg);
- snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
- "%s-lun%d", gadget->dev.bus_id, i);
+ dev_set_name(&curlun->dev,"%s-lun%d",
+ dev_name(&gadget->dev), i);
if ((rc = device_register(&curlun->dev)) != 0) {
INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 18687543d7f..1695382f30f 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -2331,7 +2331,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
udc_controller->gadget.name = driver_name;
/* Setup gadget.dev and register with kernel */
- strcpy(udc_controller->gadget.dev.bus_id, "gadget");
+ dev_set_name(&udc_controller->gadget.dev, "gadget");
udc_controller->gadget.dev.release = fsl_udc_release;
udc_controller->gadget.dev.parent = &pdev->dev;
ret = device_register(&udc_controller->gadget.dev);
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
new file mode 100644
index 00000000000..dd2f16ad5a8
--- /dev/null
+++ b/drivers/usb/gadget/g_zero.h
@@ -0,0 +1,25 @@
+/*
+ * This header declares the utility functions used by "Gadget Zero", plus
+ * interfaces to its two single-configuration function drivers.
+ */
+
+#ifndef __G_ZERO_H
+#define __G_ZERO_H
+
+#include <linux/usb/composite.h>
+
+/* global state */
+extern unsigned buflen;
+extern const struct usb_descriptor_header *otg_desc[];
+
+/* common utilities */
+struct usb_request *alloc_ep_req(struct usb_ep *ep);
+void free_ep_req(struct usb_ep *ep, struct usb_request *req);
+void disable_endpoints(struct usb_composite_dev *cdev,
+ struct usb_ep *in, struct usb_ep *out);
+
+/* configuration-specific linkup */
+int sourcesink_add(struct usb_composite_dev *cdev);
+int loopback_add(struct usb_composite_dev *cdev);
+
+#endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index ca5149ea731..5246e8fef2b 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -214,3 +214,26 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x21;
return -ENOENT;
}
+
+
+/**
+ * gadget_supports_altsettings - return true if altsettings work
+ * @gadget: the gadget in question
+ */
+static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
+{
+ /* PXA 21x/25x/26x has no altsettings at all */
+ if (gadget_is_pxa(gadget))
+ return false;
+
+ /* PXA 27x and 3xx have *broken* altsetting support */
+ if (gadget_is_pxa27x(gadget))
+ return false;
+
+ /* SH3 hardware just doesn't do altsettings */
+ if (gadget_is_sh(gadget))
+ return false;
+
+ /* Everything else is *presumably* fine ... */
+ return true;
+}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index be6613afedb..48f1c63b701 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1790,7 +1790,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.ops = &goku_ops;
/* the "gadget" abstracts/virtualizes the controller */
- strcpy(dev->gadget.dev.bus_id, "gadget");
+ dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index f132a9219e1..04692d59fc1 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -32,6 +32,7 @@
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>
#include <linux/device.h>
#include <linux/moduleparam.h>
@@ -483,8 +484,7 @@ ep_release (struct inode *inode, struct file *fd)
return 0;
}
-static int ep_ioctl (struct inode *inode, struct file *fd,
- unsigned code, unsigned long value)
+static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
{
struct ep_data *data = fd->private_data;
int status;
@@ -740,7 +740,7 @@ static const struct file_operations ep_io_operations = {
.read = ep_read,
.write = ep_write,
- .ioctl = ep_ioctl,
+ .unlocked_ioctl = ep_ioctl,
.release = ep_release,
.aio_read = ep_aio_read,
@@ -1294,15 +1294,18 @@ out:
return mask;
}
-static int dev_ioctl (struct inode *inode, struct file *fd,
- unsigned code, unsigned long value)
+static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
{
struct dev_data *dev = fd->private_data;
struct usb_gadget *gadget = dev->gadget;
+ long ret = -ENOTTY;
- if (gadget->ops->ioctl)
- return gadget->ops->ioctl (gadget, code, value);
- return -ENOTTY;
+ if (gadget->ops->ioctl) {
+ lock_kernel();
+ ret = gadget->ops->ioctl (gadget, code, value);
+ unlock_kernel();
+ }
+ return ret;
}
/* used after device configuration */
@@ -1314,7 +1317,7 @@ static const struct file_operations ep0_io_operations = {
.write = ep0_write,
.fasync = ep0_fasync,
.poll = ep0_poll,
- .ioctl = dev_ioctl,
+ .unlocked_ioctl = dev_ioctl,
.release = dev_release,
};
@@ -1964,7 +1967,7 @@ static const struct file_operations dev_init_operations = {
.open = dev_open,
.write = dev_config,
.fasync = ep0_fasync,
- .ioctl = dev_ioctl,
+ .unlocked_ioctl = dev_ioctl,
.release = dev_release,
};
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 825abd2621b..c6e7df04c69 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1970,7 +1970,7 @@ static const struct usb_gadget_ops lh7a40x_udc_ops = {
static void nop_release(struct device *dev)
{
- DEBUG("%s %s\n", __func__, dev->bus_id);
+ DEBUG("%s %s\n", __func__, dev_name(dev));
}
static struct lh7a40x_udc memory = {
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ee6b35fa870..8da7535c0c7 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1593,7 +1593,7 @@ static int __init m66592_probe(struct platform_device *pdev)
m66592->gadget.ops = &m66592_gadget_ops;
device_initialize(&m66592->gadget.dev);
- strcpy(m66592->gadget.dev.bus_id, "gadget");
+ dev_set_name(&m66592->gadget, "gadget");
m66592->gadget.is_dualspeed = 1;
m66592->gadget.dev.parent = &pdev->dev;
m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h
index 09e3ee4eeae..df886cec5ef 100644
--- a/drivers/usb/gadget/ndis.h
+++ b/drivers/usb/gadget/ndis.h
@@ -1,11 +1,11 @@
/*
- * ndis.h
- *
+ * ndis.h
+ *
* ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
- *
- * Thanks to the cygwin development team,
+ *
+ * Thanks to the cygwin development team,
* espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
- *
+ *
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index e0186230016..b67ab677af7 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2768,7 +2768,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.is_dualspeed = 1;
/* the "gadget" abstracts/virtualizes the controller */
- strcpy (dev->gadget.dev.bus_id, "gadget");
+ dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 03a7f49d207..4b79a8509e8 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2686,7 +2686,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
udc->gadget.name = driver_name;
device_initialize(&udc->gadget.dev);
- strcpy (udc->gadget.dev.bus_id, "gadget");
+ dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.dev.release = omap_udc_release;
udc->gadget.dev.parent = &odev->dev;
if (use_dma)
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index ec8f2eb041c..49cd9e145a9 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -828,9 +828,8 @@ printer_poll(struct file *fd, poll_table *wait)
return status;
}
-static int
-printer_ioctl(struct inode *inode, struct file *fd, unsigned int code,
- unsigned long arg)
+static long
+printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
{
struct printer_dev *dev = fd->private_data;
unsigned long flags;
@@ -869,7 +868,7 @@ static struct file_operations printer_io_operations = {
.write = printer_write,
.fsync = printer_fsync,
.poll = printer_poll,
- .ioctl = printer_ioctl,
+ .unlocked_ioctl = printer_ioctl,
.release = printer_close
};
@@ -1361,8 +1360,8 @@ printer_bind(struct usb_gadget *gadget)
/* Setup the sysfs files for the printer gadget. */
- dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
- "g_printer");
+ dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
+ g_printer_devno, NULL, "g_printer");
if (IS_ERR(dev->pdev)) {
ERROR(dev, "Failed to create device: g_printer\n");
goto fail;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 031dceb9302..8fb0066609b 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -152,9 +152,10 @@ static int is_vbus_present(void)
static void pullup_off(void)
{
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+ int off_level = mach->gpio_pullup_inverted;
if (mach->gpio_pullup)
- gpio_set_value(mach->gpio_pullup, 0);
+ gpio_set_value(mach->gpio_pullup, off_level);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
@@ -162,9 +163,10 @@ static void pullup_off(void)
static void pullup_on(void)
{
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
+ int on_level = !mach->gpio_pullup_inverted;
if (mach->gpio_pullup)
- gpio_set_value(mach->gpio_pullup, 1);
+ gpio_set_value(mach->gpio_pullup, on_level);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
}
@@ -1818,7 +1820,7 @@ pxa25x_udc_irq(int irq, void *_dev)
static void nop_release (struct device *dev)
{
- DMSG("%s %s\n", __func__, dev->bus_id);
+ DMSG("%s %s\n", __func__, dev_name(dev));
}
/* this uses load-time allocation and initialization (instead of
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 9c0e82ec5c4..9d447d8cfc0 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1575,7 +1575,6 @@ static void udc_enable(struct pxa_udc *udc)
{
udc_writel(udc, UDCICR0, 0);
udc_writel(udc, UDCICR1, 0);
- udc_writel(udc, UP2OCR, UP2OCR_HXOE);
udc_clear_mask_UDCCR(udc, UDCCR_UDE);
clk_enable(udc->clk);
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d0677f5d3cd..7228e856223 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1,8 +1,6 @@
/*
* RNDIS MSG parser
*
- * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
- *
* Authors: Benedikt Spranger, Pengutronix
* Robert Schwebel, Pengutronix
*
@@ -30,6 +28,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/netdevice.h>
#include <asm/io.h>
@@ -38,9 +37,7 @@
#include <asm/unaligned.h>
-#undef RNDIS_PM
-#undef RNDIS_WAKEUP
-#undef VERBOSE
+#undef VERBOSE_DEBUG
#include "rndis.h"
@@ -96,9 +93,6 @@ static const u32 oid_supported_list [] =
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_PHYSICAL_MEDIUM,
-#if 0
- OID_GEN_RNDIS_CONFIG_PARAMETER,
-#endif
/* the statistical stuff */
OID_GEN_XMIT_OK,
@@ -146,7 +140,14 @@ static const u32 oid_supported_list [] =
#endif /* RNDIS_OPTIONAL_STATS */
#ifdef RNDIS_PM
- /* PM and wakeup are mandatory for USB: */
+ /* PM and wakeup are "mandatory" for USB, but the RNDIS specs
+ * don't say what they mean ... and the NDIS specs are often
+ * confusing and/or ambiguous in this context. (That is, more
+ * so than their specs for the other OIDs.)
+ *
+ * FIXME someone who knows what these should do, please
+ * implement them!
+ */
/* power management */
OID_PNP_CAPABILITIES,
@@ -173,6 +174,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
__le32 *outbuf;
int i, count;
rndis_query_cmplt_type *resp;
+ struct net_device *net;
+ struct net_device_stats *stats;
if (!r) return -ENOMEM;
resp = (rndis_query_cmplt_type *) r->buf;
@@ -194,6 +197,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
outbuf = (__le32 *) &resp[1];
resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
+ net = rndis_per_dev_params[configNr].dev;
+ if (net->get_stats)
+ stats = net->get_stats(net);
+ else
+ stats = NULL;
+
switch (OID) {
/* general oids (table 4-1) */
@@ -350,11 +359,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_XMIT_OK:
if (rndis_debug > 1)
DBG("%s: OID_GEN_XMIT_OK\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (
- rndis_per_dev_params [configNr].stats->tx_packets -
- rndis_per_dev_params [configNr].stats->tx_errors -
- rndis_per_dev_params [configNr].stats->tx_dropped);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->tx_packets
+ - stats->tx_errors - stats->tx_dropped);
retval = 0;
}
break;
@@ -363,11 +370,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_RCV_OK:
if (rndis_debug > 1)
DBG("%s: OID_GEN_RCV_OK\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (
- rndis_per_dev_params [configNr].stats->rx_packets -
- rndis_per_dev_params [configNr].stats->rx_errors -
- rndis_per_dev_params [configNr].stats->rx_dropped);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->rx_packets
+ - stats->rx_errors - stats->rx_dropped);
retval = 0;
}
break;
@@ -376,9 +381,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_XMIT_ERROR:
if (rndis_debug > 1)
DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->tx_errors);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->tx_errors);
retval = 0;
}
break;
@@ -387,9 +391,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
case OID_GEN_RCV_ERROR:
if (rndis_debug > 1)
DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_errors);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->rx_errors);
retval = 0;
}
break;
@@ -397,150 +400,12 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_NO_BUFFER:
DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_dropped);
- retval = 0;
- }
- break;
-
-#ifdef RNDIS_OPTIONAL_STATS
- case OID_GEN_DIRECTED_BYTES_XMIT:
- DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
- /*
- * Aunt Tilly's size of shoes
- * minus antarctica count of penguins
- * divided by weight of Alpha Centauri
- */
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (
- (rndis_per_dev_params [configNr]
- .stats->tx_packets -
- rndis_per_dev_params [configNr]
- .stats->tx_errors -
- rndis_per_dev_params [configNr]
- .stats->tx_dropped)
- * 123);
- retval = 0;
- }
- break;
-
- case OID_GEN_DIRECTED_FRAMES_XMIT:
- DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
- /* dito */
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (
- (rndis_per_dev_params [configNr]
- .stats->tx_packets -
- rndis_per_dev_params [configNr]
- .stats->tx_errors -
- rndis_per_dev_params [configNr]
- .stats->tx_dropped)
- / 123);
- retval = 0;
- }
- break;
-
- case OID_GEN_MULTICAST_BYTES_XMIT:
- DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->multicast*1234);
- retval = 0;
- }
- break;
-
- case OID_GEN_MULTICAST_FRAMES_XMIT:
- DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->multicast);
- retval = 0;
- }
- break;
-
- case OID_GEN_BROADCAST_BYTES_XMIT:
- DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->tx_packets/42*255);
- retval = 0;
- }
- break;
-
- case OID_GEN_BROADCAST_FRAMES_XMIT:
- DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->tx_packets/42);
- retval = 0;
- }
- break;
-
- case OID_GEN_DIRECTED_BYTES_RCV:
- DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
- *outbuf = __constant_cpu_to_le32 (0);
- retval = 0;
- break;
-
- case OID_GEN_DIRECTED_FRAMES_RCV:
- DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
- *outbuf = __constant_cpu_to_le32 (0);
- retval = 0;
- break;
-
- case OID_GEN_MULTICAST_BYTES_RCV:
- DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->multicast * 1111);
- retval = 0;
- }
- break;
-
- case OID_GEN_MULTICAST_FRAMES_RCV:
- DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->multicast);
- retval = 0;
- }
- break;
-
- case OID_GEN_BROADCAST_BYTES_RCV:
- DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_packets/42*255);
- retval = 0;
- }
- break;
-
- case OID_GEN_BROADCAST_FRAMES_RCV:
- DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_packets/42);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->rx_dropped);
retval = 0;
}
break;
- case OID_GEN_RCV_CRC_ERROR:
- DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_crc_errors);
- retval = 0;
- }
- break;
-
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
- *outbuf = __constant_cpu_to_le32 (0);
- retval = 0;
- break;
-#endif /* RNDIS_OPTIONAL_STATS */
-
/* ieee802.3 OIDs (table 4-3) */
/* mandatory */
@@ -592,9 +457,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_RCV_ERROR_ALIGNMENT:
DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
- if (rndis_per_dev_params [configNr].stats) {
- *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
- .stats->rx_frame_errors);
+ if (stats) {
+ *outbuf = cpu_to_le32(stats->rx_frame_errors);
retval = 0;
}
break;
@@ -613,64 +477,6 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
retval = 0;
break;
-#ifdef RNDIS_OPTIONAL_STATS
- case OID_802_3_XMIT_DEFERRED:
- DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_XMIT_MAX_COLLISIONS:
- DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_RCV_OVERRUN:
- DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_XMIT_UNDERRUN:
- DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_XMIT_HEARTBEAT_FAILURE:
- DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_XMIT_TIMES_CRS_LOST:
- DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
- /* TODO */
- break;
-
- case OID_802_3_XMIT_LATE_COLLISIONS:
- DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
- /* TODO */
- break;
-#endif /* RNDIS_OPTIONAL_STATS */
-
-#ifdef RNDIS_PM
- /* power management OIDs (table 4-5) */
- case OID_PNP_CAPABILITIES:
- DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
-
- /* for now, no wakeup capabilities */
- length = sizeof (struct NDIS_PNP_CAPABILITIES);
- memset(outbuf, 0, length);
- retval = 0;
- break;
- case OID_PNP_QUERY_POWER:
- DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
- get_unaligned_le32(buf) - 1);
- /* only suspend is a real power state, and
- * it can't be entered by OID_PNP_SET_POWER...
- */
- length = 0;
- retval = 0;
- break;
-#endif
-
default:
pr_warning("%s: query unknown OID 0x%08X\n",
__func__, OID);
@@ -726,9 +532,6 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* what makes the packet flow start and stop, like
* activating the CDC Ethernet altsetting.
*/
-#ifdef RNDIS_PM
-update_linkstate:
-#endif
retval = 0;
if (*params->filter) {
params->state = RNDIS_DATA_INITIALIZED;
@@ -747,49 +550,6 @@ update_linkstate:
DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
retval = 0;
break;
-#if 0
- case OID_GEN_RNDIS_CONFIG_PARAMETER:
- {
- struct rndis_config_parameter *param;
- param = (struct rndis_config_parameter *) buf;
- DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
- __func__,
- min(cpu_to_le32(param->ParameterNameLength),80),
- buf + param->ParameterNameOffset);
- retval = 0;
- }
- break;
-#endif
-
-#ifdef RNDIS_PM
- case OID_PNP_SET_POWER:
- /* The only real power state is USB suspend, and RNDIS requests
- * can't enter it; this one isn't really about power. After
- * resuming, Windows forces a reset, and then SET_POWER D0.
- * FIXME ... then things go batty; Windows wedges itself.
- */
- i = get_unaligned_le32(buf);
- DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
- switch (i) {
- case NdisDeviceStateD0:
- *params->filter = params->saved_filter;
- goto update_linkstate;
- case NdisDeviceStateD3:
- case NdisDeviceStateD2:
- case NdisDeviceStateD1:
- params->saved_filter = *params->filter;
- retval = 0;
- break;
- }
- break;
-
-#ifdef RNDIS_WAKEUP
- // no wakeup support advertised, so wakeup OIDs always fail:
- // - OID_PNP_ENABLE_WAKE_UP
- // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
-#endif
-
-#endif /* RNDIS_PM */
default:
pr_warning("%s: set unknown OID 0x%08X, size %d\n",
@@ -807,8 +567,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
{
rndis_init_cmplt_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
- if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+ if (!params->dev)
+ return -ENOTSUPP;
r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
if (!r)
@@ -826,7 +588,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
resp->MaxTransferSize = cpu_to_le32 (
- rndis_per_dev_params [configNr].dev->mtu
+ params->dev->mtu
+ sizeof (struct ethhdr)
+ sizeof (struct rndis_packet_msg_type)
+ 22);
@@ -834,10 +596,7 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
resp->AFListOffset = __constant_cpu_to_le32 (0);
resp->AFListSize = __constant_cpu_to_le32 (0);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
-
+ params->resp_avail(params->v);
return 0;
}
@@ -845,9 +604,11 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
{
rndis_query_cmplt_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
// DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
- if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+ if (!params->dev)
+ return -ENOTSUPP;
/*
* we need more memory:
@@ -878,9 +639,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
} else
resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
+ params->resp_avail(params->v);
return 0;
}
@@ -889,6 +648,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
u32 BufLength, BufOffset;
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
if (!r)
@@ -898,7 +658,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
BufLength = le32_to_cpu (buf->InformationBufferLength);
BufOffset = le32_to_cpu (buf->InformationBufferOffset);
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
DBG("%s: Length: %d\n", __func__, BufLength);
DBG("%s: Offset: %d\n", __func__, BufOffset);
DBG("%s: InfoBuffer: ", __func__);
@@ -919,10 +679,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
else
resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
-
+ params->resp_avail(params->v);
return 0;
}
@@ -930,6 +687,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
{
rndis_reset_cmplt_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
if (!r)
@@ -942,10 +700,7 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
/* resent information */
resp->AddressingReset = __constant_cpu_to_le32 (1);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
-
+ params->resp_avail(params->v);
return 0;
}
@@ -954,6 +709,7 @@ static int rndis_keepalive_response (int configNr,
{
rndis_keepalive_cmplt_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
/* host "should" check only in RNDIS_DATA_INITIALIZED state */
@@ -968,10 +724,7 @@ static int rndis_keepalive_response (int configNr,
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
-
+ params->resp_avail(params->v);
return 0;
}
@@ -983,8 +736,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status)
{
rndis_indicate_status_msg_type *resp;
rndis_resp_t *r;
+ struct rndis_params *params = rndis_per_dev_params + configNr;
- if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
+ if (params->state == RNDIS_UNINITIALIZED)
return -ENOTSUPP;
r = rndis_add_response (configNr,
@@ -1000,9 +754,7 @@ static int rndis_indicate_status_msg (int configNr, u32 status)
resp->StatusBufferLength = __constant_cpu_to_le32 (0);
resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
- if (rndis_per_dev_params [configNr].ack)
- rndis_per_dev_params [configNr].ack (
- rndis_per_dev_params [configNr].dev);
+ params->resp_avail(params->v);
return 0;
}
@@ -1029,7 +781,6 @@ void rndis_uninit (int configNr)
if (configNr >= RNDIS_MAX_CONFIGS)
return;
- rndis_per_dev_params [configNr].used = 0;
rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
/* drain the response queue */
@@ -1142,21 +893,25 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
return -ENOTSUPP;
}
-int rndis_register (int (* rndis_control_ack) (struct net_device *))
+int rndis_register(void (*resp_avail)(void *v), void *v)
{
u8 i;
+ if (!resp_avail)
+ return -EINVAL;
+
for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
if (!rndis_per_dev_params [i].used) {
rndis_per_dev_params [i].used = 1;
- rndis_per_dev_params [i].ack = rndis_control_ack;
+ rndis_per_dev_params [i].resp_avail = resp_avail;
+ rndis_per_dev_params [i].v = v;
DBG("%s: configNr = %d\n", __func__, i);
return i;
}
}
DBG("failed\n");
- return -1;
+ return -ENODEV;
}
void rndis_deregister (int configNr)
@@ -1169,16 +924,14 @@ void rndis_deregister (int configNr)
return;
}
-int rndis_set_param_dev (u8 configNr, struct net_device *dev,
- struct net_device_stats *stats,
- u16 *cdc_filter)
+int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
{
DBG("%s:\n", __func__ );
- if (!dev || !stats) return -1;
+ if (!dev)
+ return -EINVAL;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].dev = dev;
- rndis_per_dev_params [configNr].stats = stats;
rndis_per_dev_params [configNr].filter = cdc_filter;
return 0;
@@ -1296,14 +1049,11 @@ int rndis_rm_hdr(struct sk_buff *skb)
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
- void *data)
+static int rndis_proc_show(struct seq_file *m, void *v)
{
- char *out = page;
- int len;
- rndis_params *param = (rndis_params *) data;
+ rndis_params *param = m->private;
- out += snprintf (out, count,
+ seq_printf(m,
"Config Nr. %d\n"
"used : %s\n"
"state : %s\n"
@@ -1326,25 +1076,13 @@ static int rndis_proc_read (char *page, char **start, off_t off, int count, int
(param->media_state) ? 0 : param->speed*100,
(param->media_state) ? "disconnected" : "connected",
param->vendorID, param->vendorDescr);
-
- len = out - page;
- len -= off;
-
- if (len < count) {
- *eof = 1;
- if (len <= 0)
- return 0;
- } else
- len = count;
-
- *start = page + off;
- return len;
+ return 0;
}
-static int rndis_proc_write (struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
{
- rndis_params *p = data;
+ rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
u32 speed = 0;
int i, fl_speed = 0;
@@ -1386,6 +1124,20 @@ static int rndis_proc_write (struct file *file, const char __user *buffer,
return count;
}
+static int rndis_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rndis_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations rndis_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = rndis_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = rndis_proc_write,
+};
+
#define NAME_TEMPLATE "driver/rndis-%03d"
static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
@@ -1403,7 +1155,9 @@ int __init rndis_init (void)
sprintf (name, NAME_TEMPLATE, i);
if (!(rndis_connect_state [i]
- = create_proc_entry (name, 0660, NULL)))
+ = proc_create_data(name, 0660, NULL,
+ &rndis_proc_fops,
+ (void *)(rndis_per_dev_params + i))))
{
DBG("%s :remove entries", __func__);
while (i) {
@@ -1413,11 +1167,6 @@ int __init rndis_init (void)
DBG("\n");
return -EIO;
}
-
- rndis_connect_state [i]->write_proc = rndis_proc_write;
- rndis_connect_state [i]->read_proc = rndis_proc_read;
- rndis_connect_state [i]->data = (void *)
- (rndis_per_dev_params + i);
#endif
rndis_per_dev_params [i].confignr = i;
rndis_per_dev_params [i].used = 0;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 397b149f3ca..aac61dfe0f0 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -1,8 +1,6 @@
/*
* RNDIS Definitions for Remote NDIS
*
- * Version: $Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
- *
* Authors: Benedikt Spranger, Pengutronix
* Robert Schwebel, Pengutronix
*
@@ -235,20 +233,19 @@ typedef struct rndis_params
const u8 *host_mac;
u16 *filter;
struct net_device *dev;
- struct net_device_stats *stats;
u32 vendorID;
const char *vendorDescr;
- int (*ack) (struct net_device *);
+ void (*resp_avail)(void *v);
+ void *v;
struct list_head resp_queue;
} rndis_params;
/* RNDIS Message parser and other useless functions */
int rndis_msg_parser (u8 configNr, u8 *buf);
-int rndis_register (int (*rndis_control_ack) (struct net_device *));
+int rndis_register(void (*resp_avail)(void *v), void *v);
void rndis_deregister (int configNr);
int rndis_set_param_dev (u8 configNr, struct net_device *dev,
- struct net_device_stats *stats,
u16 *cdc_filter);
int rndis_set_param_vendor (u8 configNr, u32 vendorID,
const char *vendorDescr);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index fa019fa7333..b3699afff00 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1,15 +1,9 @@
/*
- * g_serial.c -- USB gadget serial driver
+ * serial.c -- USB gadget serial driver
*
- * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com)
- *
- * This code is based in part on the Gadget Zero driver, which
- * is Copyright (C) 2003 by David Brownell, all rights reserved.
- *
- * This code also borrows from usbserial.c, which is
- * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
- * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
*
* This software is distributed under the terms of the GNU General
* Public License ("GPL") as published by the Free Software Foundation,
@@ -22,2254 +16,237 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
-
+#include "u_serial.h"
#include "gadget_chips.h"
/* Defines */
-#define GS_VERSION_STR "v2.2"
-#define GS_VERSION_NUM 0x2200
+#define GS_VERSION_STR "v2.4"
+#define GS_VERSION_NUM 0x2400
#define GS_LONG_NAME "Gadget Serial"
-#define GS_SHORT_NAME "g_serial"
-
-#define GS_MAJOR 127
-#define GS_MINOR_START 0
-
-/* REVISIT only one port is supported for now;
- * see gs_{send,recv}_packet() ... no multiplexing,
- * and no support for multiple ACM devices.
- */
-#define GS_NUM_PORTS 1
-
-#define GS_NUM_CONFIGS 1
-#define GS_NO_CONFIG_ID 0
-#define GS_BULK_CONFIG_ID 1
-#define GS_ACM_CONFIG_ID 2
-
-#define GS_MAX_NUM_INTERFACES 2
-#define GS_BULK_INTERFACE_ID 0
-#define GS_CONTROL_INTERFACE_ID 0
-#define GS_DATA_INTERFACE_ID 1
-
-#define GS_MAX_DESC_LEN 256
-
-#define GS_DEFAULT_READ_Q_SIZE 32
-#define GS_DEFAULT_WRITE_Q_SIZE 32
-
-#define GS_DEFAULT_WRITE_BUF_SIZE 8192
-#define GS_TMP_BUF_SIZE 8192
-
-#define GS_CLOSE_TIMEOUT 15
-
-#define GS_DEFAULT_USE_ACM 0
-
-/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults
- * expected by "usbser.sys" on MS-Windows.
- */
-#define GS_DEFAULT_DTE_RATE 9600
-#define GS_DEFAULT_DATA_BITS 8
-#define GS_DEFAULT_PARITY USB_CDC_NO_PARITY
-#define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
- struct usb_endpoint_descriptor *fs)
-{
- if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
- return hs;
- return fs;
-}
-
-
-/* debug settings */
-#ifdef DEBUG
-static int debug = 1;
-#else
-#define debug 0
-#endif
-
-#define gs_debug(format, arg...) \
- do { if (debug) pr_debug(format, ## arg); } while (0)
-#define gs_debug_level(level, format, arg...) \
- do { if (debug >= level) pr_debug(format, ## arg); } while (0)
+#define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR
+/*-------------------------------------------------------------------------*/
/* Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
- * Instead: allocate your own, using normal USB-IF procedures.
- */
+*
+* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
+* Instead: allocate your own, using normal USB-IF procedures.
+*/
#define GS_VENDOR_ID 0x0525 /* NetChip */
#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */
#define GS_CDC_PRODUCT_ID 0xa4a7 /* ... as CDC-ACM */
-#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET 8
+/* string IDs are assigned dynamically */
+#define STRING_MANUFACTURER_IDX 0
+#define STRING_PRODUCT_IDX 1
+#define STRING_DESCRIPTION_IDX 2
-/* circular buffer */
-struct gs_buf {
- unsigned int buf_size;
- char *buf_buf;
- char *buf_get;
- char *buf_put;
-};
+static char manufacturer[50];
-/* the port structure holds info for each port, one for each minor number */
-struct gs_port {
- struct gs_dev *port_dev; /* pointer to device struct */
- struct tty_struct *port_tty; /* pointer to tty struct */
- spinlock_t port_lock;
- int port_num;
- int port_open_count;
- int port_in_use; /* open/close in progress */
- wait_queue_head_t port_write_wait;/* waiting to write */
- struct gs_buf *port_write_buf;
- struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
- u16 port_handshake_bits;
-#define RS232_RTS (1 << 1)
-#define RS232_DTE (1 << 0)
+static struct usb_string strings_dev[] = {
+ [STRING_MANUFACTURER_IDX].s = manufacturer,
+ [STRING_PRODUCT_IDX].s = GS_VERSION_NAME,
+ [STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
+ { } /* end of list */
};
-/* the device structure holds info for the USB device */
-struct gs_dev {
- struct usb_gadget *dev_gadget; /* gadget device pointer */
- spinlock_t dev_lock; /* lock for set/reset config */
- int dev_config; /* configuration number */
- struct usb_ep *dev_notify_ep; /* address of notify endpoint */
- struct usb_ep *dev_in_ep; /* address of in endpoint */
- struct usb_ep *dev_out_ep; /* address of out endpoint */
- struct usb_endpoint_descriptor /* descriptor of notify ep */
- *dev_notify_ep_desc;
- struct usb_endpoint_descriptor /* descriptor of in endpoint */
- *dev_in_ep_desc;
- struct usb_endpoint_descriptor /* descriptor of out endpoint */
- *dev_out_ep_desc;
- struct usb_request *dev_ctrl_req; /* control request */
- struct list_head dev_req_list; /* list of write requests */
- int dev_sched_port; /* round robin port scheduled */
- struct gs_port *dev_port[GS_NUM_PORTS]; /* the ports */
+static struct usb_gadget_strings stringtab_dev = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_dev,
};
-
-/* Functions */
-
-/* tty driver internals */
-static int gs_send(struct gs_dev *dev);
-static int gs_send_packet(struct gs_dev *dev, char *packet,
- unsigned int size);
-static int gs_recv_packet(struct gs_dev *dev, char *packet,
- unsigned int size);
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req);
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req);
-
-/* gadget driver internals */
-static int gs_set_config(struct gs_dev *dev, unsigned config);
-static void gs_reset_config(struct gs_dev *dev);
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
- u8 type, unsigned int index, int is_otg);
-
-static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
- gfp_t kmalloc_flags);
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
-
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
-static void gs_free_ports(struct gs_dev *dev);
-
-/* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
-static void gs_buf_free(struct gs_buf *gb);
-static void gs_buf_clear(struct gs_buf *gb);
-static unsigned int gs_buf_data_avail(struct gs_buf *gb);
-static unsigned int gs_buf_space_avail(struct gs_buf *gb);
-static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,
- unsigned int count);
-static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
- unsigned int count);
-
-
-/* Globals */
-
-static struct gs_dev *gs_device;
-
-static struct mutex gs_open_close_lock[GS_NUM_PORTS];
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB descriptors */
-
-#define GS_MANUFACTURER_STR_ID 1
-#define GS_PRODUCT_STR_ID 2
-#define GS_SERIAL_STR_ID 3
-#define GS_BULK_CONFIG_STR_ID 4
-#define GS_ACM_CONFIG_STR_ID 5
-#define GS_CONTROL_STR_ID 6
-#define GS_DATA_STR_ID 7
-
-/* static strings, in UTF-8 */
-static char manufacturer[50];
-static struct usb_string gs_strings[] = {
- { GS_MANUFACTURER_STR_ID, manufacturer },
- { GS_PRODUCT_STR_ID, GS_LONG_NAME },
- { GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" },
- { GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" },
- { GS_CONTROL_STR_ID, "Gadget Serial Control" },
- { GS_DATA_STR_ID, "Gadget Serial Data" },
- { } /* end of list */
-};
-
-static struct usb_gadget_strings gs_string_table = {
- .language = 0x0409, /* en-us */
- .strings = gs_strings,
+static struct usb_gadget_strings *dev_strings[] = {
+ &stringtab_dev,
+ NULL,
};
-static struct usb_device_descriptor gs_device_desc = {
+static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
+ /* .bDeviceClass = f(use_acm) */
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
+ /* .bMaxPacketSize0 = f(hardware) */
.idVendor = __constant_cpu_to_le16(GS_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID),
- .iManufacturer = GS_MANUFACTURER_STR_ID,
- .iProduct = GS_PRODUCT_STR_ID,
- .bNumConfigurations = GS_NUM_CONFIGS,
+ /* .idProduct = f(use_acm) */
+ /* .bcdDevice = f(hardware) */
+ /* .iManufacturer = DYNAMIC */
+ /* .iProduct = DYNAMIC */
+ .bNumConfigurations = 1,
};
-static struct usb_otg_descriptor gs_otg_descriptor = {
- .bLength = sizeof(gs_otg_descriptor),
+static struct usb_otg_descriptor otg_descriptor = {
+ .bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-static struct usb_config_descriptor gs_bulk_config_desc = {
- .bLength = USB_DT_CONFIG_SIZE,
- .bDescriptorType = USB_DT_CONFIG,
- /* .wTotalLength computed dynamically */
- .bNumInterfaces = 1,
- .bConfigurationValue = GS_BULK_CONFIG_ID,
- .iConfiguration = GS_BULK_CONFIG_STR_ID,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1,
-};
-
-static struct usb_config_descriptor gs_acm_config_desc = {
- .bLength = USB_DT_CONFIG_SIZE,
- .bDescriptorType = USB_DT_CONFIG,
- /* .wTotalLength computed dynamically */
- .bNumInterfaces = 2,
- .bConfigurationValue = GS_ACM_CONFIG_ID,
- .iConfiguration = GS_ACM_CONFIG_STR_ID,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1,
-};
-
-static const struct usb_interface_descriptor gs_bulk_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = GS_BULK_INTERFACE_ID,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = GS_DATA_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_control_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = GS_CONTROL_INTERFACE_ID,
- .bNumEndpoints = 1,
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
- .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
- .iInterface = GS_CONTROL_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_data_interface_desc = {
- .bLength = USB_DT_INTERFACE_SIZE,
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = GS_DATA_INTERFACE_ID,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_CDC_DATA,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = GS_DATA_STR_ID,
-};
-
-static const struct usb_cdc_header_desc gs_header_desc = {
- .bLength = sizeof(gs_header_desc),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_HEADER_TYPE,
- .bcdCDC = __constant_cpu_to_le16(0x0110),
-};
-
-static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
- .bLength = sizeof(gs_call_mgmt_descriptor),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
- .bmCapabilities = 0,
- .bDataInterface = 1, /* index of data interface */
-};
-
-static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
- .bLength = sizeof(gs_acm_descriptor),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_ACM_TYPE,
- .bmCapabilities = (1 << 1),
-};
-
-static const struct usb_cdc_union_desc gs_union_desc = {
- .bLength = sizeof(gs_union_desc),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_UNION_TYPE,
- .bMasterInterface0 = 0, /* index of control interface */
- .bSlaveInterface0 = 1, /* index of data interface */
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = {
- (struct usb_descriptor_header *) &gs_otg_descriptor,
- (struct usb_descriptor_header *) &gs_bulk_interface_desc,
- (struct usb_descriptor_header *) &gs_fullspeed_in_desc,
- (struct usb_descriptor_header *) &gs_fullspeed_out_desc,
- NULL,
-};
-
-static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = {
- (struct usb_descriptor_header *) &gs_otg_descriptor,
- (struct usb_descriptor_header *) &gs_control_interface_desc,
- (struct usb_descriptor_header *) &gs_header_desc,
- (struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
- (struct usb_descriptor_header *) &gs_acm_descriptor,
- (struct usb_descriptor_header *) &gs_union_desc,
- (struct usb_descriptor_header *) &gs_fullspeed_notify_desc,
- (struct usb_descriptor_header *) &gs_data_interface_desc,
- (struct usb_descriptor_header *) &gs_fullspeed_in_desc,
- (struct usb_descriptor_header *) &gs_fullspeed_out_desc,
- NULL,
-};
-static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_INT,
- .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor gs_qualifier_desc = {
- .bLength = sizeof(struct usb_qualifier_descriptor),
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
- .bcdUSB = __constant_cpu_to_le16 (0x0200),
- /* assumes ep0 uses the same value for both speeds ... */
- .bNumConfigurations = GS_NUM_CONFIGS,
-};
-
-static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = {
- (struct usb_descriptor_header *) &gs_otg_descriptor,
- (struct usb_descriptor_header *) &gs_bulk_interface_desc,
- (struct usb_descriptor_header *) &gs_highspeed_in_desc,
- (struct usb_descriptor_header *) &gs_highspeed_out_desc,
- NULL,
+ /* REVISIT SRP-only hardware is possible, although
+ * it would not be called "OTG" ...
+ */
+ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
-static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {
- (struct usb_descriptor_header *) &gs_otg_descriptor,
- (struct usb_descriptor_header *) &gs_control_interface_desc,
- (struct usb_descriptor_header *) &gs_header_desc,
- (struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
- (struct usb_descriptor_header *) &gs_acm_descriptor,
- (struct usb_descriptor_header *) &gs_union_desc,
- (struct usb_descriptor_header *) &gs_highspeed_notify_desc,
- (struct usb_descriptor_header *) &gs_data_interface_desc,
- (struct usb_descriptor_header *) &gs_highspeed_in_desc,
- (struct usb_descriptor_header *) &gs_highspeed_out_desc,
+static const struct usb_descriptor_header *otg_desc[] = {
+ (struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
-
/*-------------------------------------------------------------------------*/
/* Module */
-MODULE_DESCRIPTION(GS_LONG_NAME);
+MODULE_DESCRIPTION(GS_VERSION_NAME);
MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
-#ifdef DEBUG
-module_param(debug, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
-#endif
-
-static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
-module_param(read_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
-
-static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
-module_param(write_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
+static int use_acm = true;
+module_param(use_acm, bool, 0);
+MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
-static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
-module_param(write_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
-
-static unsigned int use_acm = GS_DEFAULT_USE_ACM;
-module_param(use_acm, uint, S_IRUGO);
-MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no");
+static unsigned n_ports = 1;
+module_param(n_ports, uint, 0);
+MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
/*-------------------------------------------------------------------------*/
-/* TTY Driver */
-
-/*
- * gs_open
- */
-static int gs_open(struct tty_struct *tty, struct file *file)
-{
- int port_num;
- unsigned long flags;
- struct gs_port *port;
- struct gs_dev *dev;
- struct gs_buf *buf;
- struct mutex *mtx;
- int ret;
-
- port_num = tty->index;
-
- gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
-
- if (port_num < 0 || port_num >= GS_NUM_PORTS) {
- pr_err("gs_open: (%d,%p,%p) invalid port number\n",
- port_num, tty, file);
- return -ENODEV;
- }
-
- dev = gs_device;
-
- if (dev == NULL) {
- pr_err("gs_open: (%d,%p,%p) NULL device pointer\n",
- port_num, tty, file);
- return -ENODEV;
- }
-
- mtx = &gs_open_close_lock[port_num];
- if (mutex_lock_interruptible(mtx)) {
- pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
- port_num, tty, file);
- return -ERESTARTSYS;
- }
-
- spin_lock_irqsave(&dev->dev_lock, flags);
-
- if (dev->dev_config == GS_NO_CONFIG_ID) {
- pr_err("gs_open: (%d,%p,%p) device is not connected\n",
- port_num, tty, file);
- ret = -ENODEV;
- goto exit_unlock_dev;
- }
-
- port = dev->dev_port[port_num];
-
- if (port == NULL) {
- pr_err("gs_open: (%d,%p,%p) NULL port pointer\n",
- port_num, tty, file);
- ret = -ENODEV;
- goto exit_unlock_dev;
- }
-
- spin_lock(&port->port_lock);
- spin_unlock(&dev->dev_lock);
-
- if (port->port_dev == NULL) {
- pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n",
- port_num, tty, file);
- ret = -EIO;
- goto exit_unlock_port;
- }
-
- if (port->port_open_count > 0) {
- ++port->port_open_count;
- gs_debug("gs_open: (%d,%p,%p) already open\n",
- port_num, tty, file);
- ret = 0;
- goto exit_unlock_port;
- }
-
- tty->driver_data = NULL;
-
- /* mark port as in use, we can drop port lock and sleep if necessary */
- port->port_in_use = 1;
-
- /* allocate write buffer on first open */
- if (port->port_write_buf == NULL) {
- spin_unlock_irqrestore(&port->port_lock, flags);
- buf = gs_buf_alloc(write_buf_size, GFP_KERNEL);
- spin_lock_irqsave(&port->port_lock, flags);
-
- /* might have been disconnected while asleep, check */
- if (port->port_dev == NULL) {
- pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n",
- port_num, tty, file);
- port->port_in_use = 0;
- ret = -EIO;
- goto exit_unlock_port;
- }
-
- if ((port->port_write_buf=buf) == NULL) {
- pr_err("gs_open: (%d,%p,%p) cannot allocate "
- "port write buffer\n",
- port_num, tty, file);
- port->port_in_use = 0;
- ret = -ENOMEM;
- goto exit_unlock_port;
- }
-
- }
-
- /* wait for carrier detect (not implemented) */
-
- /* might have been disconnected while asleep, check */
- if (port->port_dev == NULL) {
- pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n",
- port_num, tty, file);
- port->port_in_use = 0;
- ret = -EIO;
- goto exit_unlock_port;
- }
-
- tty->driver_data = port;
- port->port_tty = tty;
- port->port_open_count = 1;
- port->port_in_use = 0;
-
- gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file);
-
- ret = 0;
-
-exit_unlock_port:
- spin_unlock_irqrestore(&port->port_lock, flags);
- mutex_unlock(mtx);
- return ret;
-
-exit_unlock_dev:
- spin_unlock_irqrestore(&dev->dev_lock, flags);
- mutex_unlock(mtx);
- return ret;
-
-}
-
-/*
- * gs_close
- */
-
-static int gs_write_finished_event_safely(struct gs_port *p)
-{
- int cond;
-
- spin_lock_irq(&(p)->port_lock);
- cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf);
- spin_unlock_irq(&(p)->port_lock);
- return cond;
-}
-
-static void gs_close(struct tty_struct *tty, struct file *file)
-{
- struct gs_port *port = tty->driver_data;
- struct mutex *mtx;
-
- if (port == NULL) {
- pr_err("gs_close: NULL port pointer\n");
- return;
- }
-
- gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);
-
- mtx = &gs_open_close_lock[port->port_num];
- mutex_lock(mtx);
-
- spin_lock_irq(&port->port_lock);
-
- if (port->port_open_count == 0) {
- pr_err("gs_close: (%d,%p,%p) port is already closed\n",
- port->port_num, tty, file);
- goto exit;
- }
-
- if (port->port_open_count > 1) {
- --port->port_open_count;
- goto exit;
- }
-
- /* free disconnected port on final close */
- if (port->port_dev == NULL) {
- kfree(port);
- goto exit;
- }
-
- /* mark port as closed but in use, we can drop port lock */
- /* and sleep if necessary */
- port->port_in_use = 1;
- port->port_open_count = 0;
-
- /* wait for write buffer to drain, or */
- /* at most GS_CLOSE_TIMEOUT seconds */
- if (gs_buf_data_avail(port->port_write_buf) > 0) {
- spin_unlock_irq(&port->port_lock);
- wait_event_interruptible_timeout(port->port_write_wait,
- gs_write_finished_event_safely(port),
- GS_CLOSE_TIMEOUT * HZ);
- spin_lock_irq(&port->port_lock);
- }
-
- /* free disconnected port on final close */
- /* (might have happened during the above sleep) */
- if (port->port_dev == NULL) {
- kfree(port);
- goto exit;
- }
-
- gs_buf_clear(port->port_write_buf);
-
- tty->driver_data = NULL;
- port->port_tty = NULL;
- port->port_in_use = 0;
-
- gs_debug("gs_close: (%d,%p,%p) completed\n",
- port->port_num, tty, file);
-
-exit:
- spin_unlock_irq(&port->port_lock);
- mutex_unlock(mtx);
-}
-
-/*
- * gs_write
- */
-static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
+static int __init serial_bind_config(struct usb_configuration *c)
{
- unsigned long flags;
- struct gs_port *port = tty->driver_data;
- int ret;
-
- if (port == NULL) {
- pr_err("gs_write: NULL port pointer\n");
- return -EIO;
- }
-
- gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,
- count);
-
- if (count == 0)
- return 0;
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_dev == NULL) {
- pr_err("gs_write: (%d,%p) port is not connected\n",
- port->port_num, tty);
- ret = -EIO;
- goto exit;
- }
-
- if (port->port_open_count == 0) {
- pr_err("gs_write: (%d,%p) port is closed\n",
- port->port_num, tty);
- ret = -EBADF;
- goto exit;
- }
-
- count = gs_buf_put(port->port_write_buf, buf, count);
-
- spin_unlock_irqrestore(&port->port_lock, flags);
-
- gs_send(gs_device);
-
- gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,
- count);
+ unsigned i;
+ int status = 0;
- return count;
-
-exit:
- spin_unlock_irqrestore(&port->port_lock, flags);
- return ret;
-}
-
-/*
- * gs_put_char
- */
-static int gs_put_char(struct tty_struct *tty, unsigned char ch)
-{
- unsigned long flags;
- struct gs_port *port = tty->driver_data;
- int ret = 0;
-
- if (port == NULL) {
- pr_err("gs_put_char: NULL port pointer\n");
- return 0;
- }
-
- gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
- port->port_num, tty, ch, __builtin_return_address(0));
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_dev == NULL) {
- pr_err("gs_put_char: (%d,%p) port is not connected\n",
- port->port_num, tty);
- goto exit;
- }
-
- if (port->port_open_count == 0) {
- pr_err("gs_put_char: (%d,%p) port is closed\n",
- port->port_num, tty);
- goto exit;
- }
-
- ret = gs_buf_put(port->port_write_buf, &ch, 1);
-
-exit:
- spin_unlock_irqrestore(&port->port_lock, flags);
- return ret;
-}
-
-/*
- * gs_flush_chars
- */
-static void gs_flush_chars(struct tty_struct *tty)
-{
- unsigned long flags;
- struct gs_port *port = tty->driver_data;
-
- if (port == NULL) {
- pr_err("gs_flush_chars: NULL port pointer\n");
- return;
- }
-
- gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_dev == NULL) {
- pr_err("gs_flush_chars: (%d,%p) port is not connected\n",
- port->port_num, tty);
- goto exit;
- }
-
- if (port->port_open_count == 0) {
- pr_err("gs_flush_chars: (%d,%p) port is closed\n",
- port->port_num, tty);
- goto exit;
- }
-
- spin_unlock_irqrestore(&port->port_lock, flags);
-
- gs_send(gs_device);
-
- return;
-
-exit:
- spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-/*
- * gs_write_room
- */
-static int gs_write_room(struct tty_struct *tty)
-{
-
- int room = 0;
- unsigned long flags;
- struct gs_port *port = tty->driver_data;
-
-
- if (port == NULL)
- return 0;
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_dev != NULL && port->port_open_count > 0
- && port->port_write_buf != NULL)
- room = gs_buf_space_avail(port->port_write_buf);
-
- spin_unlock_irqrestore(&port->port_lock, flags);
-
- gs_debug("gs_write_room: (%d,%p) room=%d\n",
- port->port_num, tty, room);
-
- return room;
-}
-
-/*
- * gs_chars_in_buffer
- */
-static int gs_chars_in_buffer(struct tty_struct *tty)
-{
- int chars = 0;
- unsigned long flags;
- struct gs_port *port = tty->driver_data;
-
- if (port == NULL)
- return 0;
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_dev != NULL && port->port_open_count > 0
- && port->port_write_buf != NULL)
- chars = gs_buf_data_avail(port->port_write_buf);
-
- spin_unlock_irqrestore(&port->port_lock, flags);
-
- gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
- port->port_num, tty, chars);
-
- return chars;
-}
-
-/*
- * gs_throttle
- */
-static void gs_throttle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_unthrottle
- */
-static void gs_unthrottle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_break
- */
-static void gs_break(struct tty_struct *tty, int break_state)
-{
-}
-
-/*
- * gs_ioctl
- */
-static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct gs_port *port = tty->driver_data;
-
- if (port == NULL) {
- pr_err("gs_ioctl: NULL port pointer\n");
- return -EIO;
+ for (i = 0; i < n_ports && status == 0; i++) {
+ if (use_acm)
+ status = acm_bind_config(c, i);
+ else
+ status = gser_bind_config(c, i);
}
-
- gs_debug("gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",
- port->port_num, tty, file, cmd, arg);
-
- /* handle ioctls */
-
- /* could not handle ioctl */
- return -ENOIOCTLCMD;
-}
-
-/*
- * gs_set_termios
- */
-static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
-{
+ return status;
}
-static const struct tty_operations gs_tty_ops = {
- .open = gs_open,
- .close = gs_close,
- .write = gs_write,
- .put_char = gs_put_char,
- .flush_chars = gs_flush_chars,
- .write_room = gs_write_room,
- .ioctl = gs_ioctl,
- .set_termios = gs_set_termios,
- .throttle = gs_throttle,
- .unthrottle = gs_unthrottle,
- .break_ctl = gs_break,
- .chars_in_buffer = gs_chars_in_buffer,
+static struct usb_configuration serial_config_driver = {
+ /* .label = f(use_acm) */
+ .bind = serial_bind_config,
+ /* .bConfigurationValue = f(use_acm) */
+ /* .iConfiguration = DYNAMIC */
+ .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1, /* 2 mA, minimal */
};
-/*-------------------------------------------------------------------------*/
-
-/*
-* gs_send
-*
-* This function finds available write requests, calls
-* gs_send_packet to fill these packets with data, and
-* continues until either there are no more write requests
-* available or no more data to send. This function is
-* run whenever data arrives or write requests are available.
-*/
-static int gs_send(struct gs_dev *dev)
-{
- int ret,len;
- unsigned long flags;
- struct usb_ep *ep;
- struct usb_request *req;
-
- if (dev == NULL) {
- pr_err("gs_send: NULL device pointer\n");
- return -ENODEV;
- }
-
- spin_lock_irqsave(&dev->dev_lock, flags);
-
- ep = dev->dev_in_ep;
-
- while(!list_empty(&dev->dev_req_list)) {
-
- req = list_entry(dev->dev_req_list.next,
- struct usb_request, list);
-
- len = gs_send_packet(dev, req->buf, ep->maxpacket);
-
- if (len > 0) {
- gs_debug_level(3, "gs_send: len=%d, 0x%2.2x "
- "0x%2.2x 0x%2.2x ...\n", len,
- *((unsigned char *)req->buf),
- *((unsigned char *)req->buf+1),
- *((unsigned char *)req->buf+2));
- list_del(&req->list);
- req->length = len;
- spin_unlock_irqrestore(&dev->dev_lock, flags);
- if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
- pr_err(
- "gs_send: cannot queue read request, ret=%d\n",
- ret);
- spin_lock_irqsave(&dev->dev_lock, flags);
- break;
- }
- spin_lock_irqsave(&dev->dev_lock, flags);
- } else {
- break;
- }
-
- }
-
- spin_unlock_irqrestore(&dev->dev_lock, flags);
-
- return 0;
-}
-
-/*
- * gs_send_packet
- *
- * If there is data to send, a packet is built in the given
- * buffer and the size is returned. If there is no data to
- * send, 0 is returned. If there is any error a negative
- * error number is returned.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
- unsigned int len;
- struct gs_port *port;
-
- /* TEMPORARY -- only port 0 is supported right now */
- port = dev->dev_port[0];
-
- if (port == NULL) {
- pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0);
- return -EIO;
- }
-
- spin_lock(&port->port_lock);
-
- len = gs_buf_data_avail(port->port_write_buf);
- if (len < size)
- size = len;
-
- if (size == 0)
- goto exit;
-
- size = gs_buf_get(port->port_write_buf, packet, size);
-
- if (port->port_tty)
- wake_up_interruptible(&port->port_tty->write_wait);
-
-exit:
- spin_unlock(&port->port_lock);
- return size;
-}
-
-/*
- * gs_recv_packet
- *
- * Called for each USB packet received. Reads the packet
- * header and stuffs the data in the appropriate tty buffer.
- * Returns 0 if successful, or a negative error number.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
- unsigned int len;
- struct gs_port *port;
- int ret;
- struct tty_struct *tty;
-
- /* TEMPORARY -- only port 0 is supported right now */
- port = dev->dev_port[0];
-
- if (port == NULL) {
- pr_err("gs_recv_packet: port=%d, NULL port pointer\n",
- port->port_num);
- return -EIO;
- }
-
- spin_lock(&port->port_lock);
-
- if (port->port_open_count == 0) {
- pr_err("gs_recv_packet: port=%d, port is closed\n",
- port->port_num);
- ret = -EIO;
- goto exit;
- }
-
-
- tty = port->port_tty;
-
- if (tty == NULL) {
- pr_err("gs_recv_packet: port=%d, NULL tty pointer\n",
- port->port_num);
- ret = -EIO;
- goto exit;
- }
-
- if (port->port_tty->magic != TTY_MAGIC) {
- pr_err("gs_recv_packet: port=%d, bad tty magic\n",
- port->port_num);
- ret = -EIO;
- goto exit;
- }
-
- len = tty_buffer_request_room(tty, size);
- if (len > 0) {
- tty_insert_flip_string(tty, packet, len);
- tty_flip_buffer_push(port->port_tty);
- wake_up_interruptible(&port->port_tty->read_wait);
- }
- ret = 0;
-exit:
- spin_unlock(&port->port_lock);
- return ret;
-}
-
-/*
-* gs_read_complete
-*/
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+static int __init gs_bind(struct usb_composite_dev *cdev)
{
- int ret;
- struct gs_dev *dev = ep->driver_data;
-
- if (dev == NULL) {
- pr_err("gs_read_complete: NULL device pointer\n");
- return;
- }
+ int gcnum;
+ struct usb_gadget *gadget = cdev->gadget;
+ int status;
- switch(req->status) {
- case 0:
- /* normal completion */
- gs_recv_packet(dev, req->buf, req->actual);
-requeue:
- req->length = ep->maxpacket;
- if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
- pr_err(
- "gs_read_complete: cannot queue read request, ret=%d\n",
- ret);
- }
- break;
-
- case -ESHUTDOWN:
- /* disconnect */
- gs_debug("gs_read_complete: shutdown\n");
- gs_free_req(ep, req);
- break;
-
- default:
- /* unexpected */
- pr_err(
- "gs_read_complete: unexpected status error, status=%d\n",
- req->status);
- goto requeue;
- break;
- }
-}
-
-/*
-* gs_write_complete
-*/
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct gs_dev *dev = ep->driver_data;
-
- if (dev == NULL) {
- pr_err("gs_write_complete: NULL device pointer\n");
- return;
- }
+ status = gserial_setup(cdev->gadget, n_ports);
+ if (status < 0)
+ return status;
- switch(req->status) {
- case 0:
- /* normal completion */
-requeue:
- spin_lock(&dev->dev_lock);
- list_add(&req->list, &dev->dev_req_list);
- spin_unlock(&dev->dev_lock);
-
- gs_send(dev);
-
- break;
-
- case -ESHUTDOWN:
- /* disconnect */
- gs_debug("gs_write_complete: shutdown\n");
- gs_free_req(ep, req);
- break;
-
- default:
- pr_err(
- "gs_write_complete: unexpected status error, status=%d\n",
- req->status);
- goto requeue;
- break;
- }
-}
+ /* Allocate string descriptor numbers ... note that string
+ * contents can be overridden by the composite_dev glue.
+ */
-/*-------------------------------------------------------------------------*/
+ /* device description: manufacturer, product */
+ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+ init_utsname()->sysname, init_utsname()->release,
+ gadget->name);
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail;
+ strings_dev[STRING_MANUFACTURER_IDX].id = status;
-/* Gadget Driver */
+ device_desc.iManufacturer = status;
-/*
- * gs_unbind
- *
- * Called on module unload. Frees the control request and device
- * structure.
- */
-static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
-{
- struct gs_dev *dev = get_gadget_data(gadget);
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail;
+ strings_dev[STRING_PRODUCT_IDX].id = status;
- gs_device = NULL;
+ device_desc.iProduct = status;
- /* read/write requests already freed, only control request remains */
- if (dev != NULL) {
- if (dev->dev_ctrl_req != NULL) {
- gs_free_req(gadget->ep0, dev->dev_ctrl_req);
- dev->dev_ctrl_req = NULL;
- }
- gs_reset_config(dev);
- gs_free_ports(dev);
- kfree(dev);
- set_gadget_data(gadget, NULL);
- }
+ /* config description */
+ status = usb_string_id(cdev);
+ if (status < 0)
+ goto fail;
+ strings_dev[STRING_DESCRIPTION_IDX].id = status;
- pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
- GS_VERSION_STR);
-}
-
-/*
- * gs_bind
- *
- * Called on module load. Allocates and initializes the device
- * structure and a control request.
- */
-static int __init gs_bind(struct usb_gadget *gadget)
-{
- int ret;
- struct usb_ep *ep;
- struct gs_dev *dev;
- int gcnum;
-
- /* Some controllers can't support CDC ACM:
- * - sh doesn't support multiple interfaces or configs;
- * - sa1100 doesn't have a third interrupt endpoint
- */
- if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
- use_acm = 0;
+ serial_config_driver.iConfiguration = status;
+ /* set up other descriptors */
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
- gs_device_desc.bcdDevice =
- cpu_to_le16(GS_VERSION_NUM | gcnum);
+ device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum);
else {
+ /* this is so simple (for now, no altsettings) that it
+ * SHOULD NOT have problems with bulk-capable hardware.
+ * so warn about unrcognized controllers -- don't panic.
+ *
+ * things like configuration and altsetting numbering
+ * can need hardware-specific attention though.
+ */
pr_warning("gs_bind: controller '%s' not recognized\n",
gadget->name);
- /* unrecognized, but safe unless bulk is REALLY quirky */
- gs_device_desc.bcdDevice =
- __constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
- }
-
- dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
- if (dev == NULL)
- return -ENOMEM;
-
- usb_ep_autoconfig_reset(gadget);
-
- ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
- if (!ep)
- goto autoconf_fail;
- dev->dev_in_ep = ep;
- ep->driver_data = dev; /* claim the endpoint */
-
- ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
- if (!ep)
- goto autoconf_fail;
- dev->dev_out_ep = ep;
- ep->driver_data = dev; /* claim the endpoint */
-
- if (use_acm) {
- ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
- if (!ep) {
- pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
- goto autoconf_fail;
- }
- gs_device_desc.idProduct = __constant_cpu_to_le16(
- GS_CDC_PRODUCT_ID),
- dev->dev_notify_ep = ep;
- ep->driver_data = dev; /* claim the endpoint */
- }
-
- gs_device_desc.bDeviceClass = use_acm
- ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
- gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
- if (gadget_is_dualspeed(gadget)) {
- gs_qualifier_desc.bDeviceClass = use_acm
- ? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
- /* assume ep0 uses the same packet size for both speeds */
- gs_qualifier_desc.bMaxPacketSize0 =
- gs_device_desc.bMaxPacketSize0;
- /* assume endpoints are dual-speed */
- gs_highspeed_notify_desc.bEndpointAddress =
- gs_fullspeed_notify_desc.bEndpointAddress;
- gs_highspeed_in_desc.bEndpointAddress =
- gs_fullspeed_in_desc.bEndpointAddress;
- gs_highspeed_out_desc.bEndpointAddress =
- gs_fullspeed_out_desc.bEndpointAddress;
- }
-
- usb_gadget_set_selfpowered(gadget);
-
- if (gadget_is_otg(gadget)) {
- gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
- gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ device_desc.bcdDevice =
+ __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099);
}
- gs_device = dev;
-
- snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
- init_utsname()->sysname, init_utsname()->release,
- gadget->name);
-
- dev->dev_gadget = gadget;
- spin_lock_init(&dev->dev_lock);
- INIT_LIST_HEAD(&dev->dev_req_list);
- set_gadget_data(gadget, dev);
-
- if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
- pr_err("gs_bind: cannot allocate ports\n");
- gs_unbind(gadget);
- return ret;
+ if (gadget_is_otg(cdev->gadget)) {
+ serial_config_driver.descriptors = otg_desc;
+ serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- /* preallocate control response and buffer */
- dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN,
- GFP_KERNEL);
- if (dev->dev_ctrl_req == NULL) {
- gs_unbind(gadget);
- return -ENOMEM;
- }
- gadget->ep0->driver_data = dev;
+ /* register our configuration */
+ status = usb_add_config(cdev, &serial_config_driver);
+ if (status < 0)
+ goto fail;
- pr_info("gs_bind: %s %s bound\n",
- GS_LONG_NAME, GS_VERSION_STR);
+ INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
-autoconf_fail:
- kfree(dev);
- pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
- return -ENODEV;
-}
-
-static int gs_setup_standard(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *ctrl)
-{
- int ret = -EOPNOTSUPP;
- struct gs_dev *dev = get_gadget_data(gadget);
- struct usb_request *req = dev->dev_ctrl_req;
- u16 wIndex = le16_to_cpu(ctrl->wIndex);
- u16 wValue = le16_to_cpu(ctrl->wValue);
- u16 wLength = le16_to_cpu(ctrl->wLength);
-
- switch (ctrl->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
-
- switch (wValue >> 8) {
- case USB_DT_DEVICE:
- ret = min(wLength,
- (u16)sizeof(struct usb_device_descriptor));
- memcpy(req->buf, &gs_device_desc, ret);
- break;
-
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
- break;
- ret = min(wLength,
- (u16)sizeof(struct usb_qualifier_descriptor));
- memcpy(req->buf, &gs_qualifier_desc, ret);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
- break;
- /* fall through */
- case USB_DT_CONFIG:
- ret = gs_build_config_buf(req->buf, gadget,
- wValue >> 8, wValue & 0xff,
- gadget_is_otg(gadget));
- if (ret >= 0)
- ret = min(wLength, (u16)ret);
- break;
-
- case USB_DT_STRING:
- /* wIndex == language code. */
- ret = usb_gadget_get_string(&gs_string_table,
- wValue & 0xff, req->buf);
- if (ret >= 0)
- ret = min(wLength, (u16)ret);
- break;
- }
- break;
-
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- break;
- spin_lock(&dev->dev_lock);
- ret = gs_set_config(dev, wValue);
- spin_unlock(&dev->dev_lock);
- break;
-
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- break;
- *(u8 *)req->buf = dev->dev_config;
- ret = min(wLength, (u16)1);
- break;
-
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE
- || !dev->dev_config
- || wIndex >= GS_MAX_NUM_INTERFACES)
- break;
- if (dev->dev_config == GS_BULK_CONFIG_ID
- && wIndex != GS_BULK_INTERFACE_ID)
- break;
- /* no alternate interface settings */
- if (wValue != 0)
- break;
- spin_lock(&dev->dev_lock);
- /* PXA hardware partially handles SET_INTERFACE;
- * we need to kluge around that interference. */
- if (gadget_is_pxa(gadget)) {
- ret = gs_set_config(dev, use_acm ?
- GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID);
- goto set_interface_done;
- }
- if (dev->dev_config != GS_BULK_CONFIG_ID
- && wIndex == GS_CONTROL_INTERFACE_ID) {
- if (dev->dev_notify_ep) {
- usb_ep_disable(dev->dev_notify_ep);
- usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);
- }
- } else {
- usb_ep_disable(dev->dev_in_ep);
- usb_ep_disable(dev->dev_out_ep);
- usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc);
- usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc);
- }
- ret = 0;
-set_interface_done:
- spin_unlock(&dev->dev_lock);
- break;
-
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
- || dev->dev_config == GS_NO_CONFIG_ID)
- break;
- if (wIndex >= GS_MAX_NUM_INTERFACES
- || (dev->dev_config == GS_BULK_CONFIG_ID
- && wIndex != GS_BULK_INTERFACE_ID)) {
- ret = -EDOM;
- break;
- }
- /* no alternate interface settings */
- *(u8 *)req->buf = 0;
- ret = min(wLength, (u16)1);
- break;
-
- default:
- pr_err("gs_setup: unknown standard request, type=%02x, "
- "request=%02x, value=%04x, index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- wValue, wIndex, wLength);
- break;
- }
-
- return ret;
+fail:
+ gserial_cleanup();
+ return status;
}
-static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
- struct usb_request *req)
-{
- struct gs_dev *dev = ep->driver_data;
- struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
-
- switch (req->status) {
- case 0:
- /* normal completion */
- if (req->actual != sizeof(port->port_line_coding))
- usb_ep_set_halt(ep);
- else if (port) {
- struct usb_cdc_line_coding *value = req->buf;
-
- /* REVISIT: we currently just remember this data.
- * If we change that, (a) validate it first, then
- * (b) update whatever hardware needs updating.
- */
- spin_lock(&port->port_lock);
- port->port_line_coding = *value;
- spin_unlock(&port->port_lock);
- }
- break;
-
- case -ESHUTDOWN:
- /* disconnect */
- gs_free_req(ep, req);
- break;
-
- default:
- /* unexpected */
- break;
- }
- return;
-}
-
-static int gs_setup_class(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *ctrl)
-{
- int ret = -EOPNOTSUPP;
- struct gs_dev *dev = get_gadget_data(gadget);
- struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
- struct usb_request *req = dev->dev_ctrl_req;
- u16 wIndex = le16_to_cpu(ctrl->wIndex);
- u16 wValue = le16_to_cpu(ctrl->wValue);
- u16 wLength = le16_to_cpu(ctrl->wLength);
-
- switch (ctrl->bRequest) {
- case USB_CDC_REQ_SET_LINE_CODING:
- if (wLength != sizeof(struct usb_cdc_line_coding))
- break;
- ret = wLength;
- req->complete = gs_setup_complete_set_line_coding;
- break;
-
- case USB_CDC_REQ_GET_LINE_CODING:
- ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding));
- if (port) {
- spin_lock(&port->port_lock);
- memcpy(req->buf, &port->port_line_coding, ret);
- spin_unlock(&port->port_lock);
- }
- break;
-
- case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
- if (wLength != 0)
- break;
- ret = 0;
- if (port) {
- /* REVISIT: we currently just remember this data.
- * If we change that, update whatever hardware needs
- * updating.
- */
- spin_lock(&port->port_lock);
- port->port_handshake_bits = wValue;
- spin_unlock(&port->port_lock);
- }
- break;
-
- default:
- /* NOTE: strictly speaking, we should accept AT-commands
- * using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE.
- * But our call management descriptor says we don't handle
- * call management, so we should be able to get by without
- * handling those "required" commands (except by stalling).
- */
- pr_err("gs_setup: unknown class request, "
- "type=%02x, request=%02x, value=%04x, "
- "index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- wValue, wIndex, wLength);
- break;
- }
-
- return ret;
-}
-
-/*
- * gs_setup_complete
- */
-static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length) {
- pr_err("gs_setup_complete: status error, status=%d, "
- "actual=%d, length=%d\n",
- req->status, req->actual, req->length);
- }
-}
-
-/*
- * gs_setup
- *
- * Implements all the control endpoint functionality that's not
- * handled in hardware or the hardware driver.
- *
- * Returns the size of the data sent to the host, or a negative
- * error number.
- */
-static int gs_setup(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *ctrl)
-{
- int ret = -EOPNOTSUPP;
- struct gs_dev *dev = get_gadget_data(gadget);
- struct usb_request *req = dev->dev_ctrl_req;
- u16 wIndex = le16_to_cpu(ctrl->wIndex);
- u16 wValue = le16_to_cpu(ctrl->wValue);
- u16 wLength = le16_to_cpu(ctrl->wLength);
-
- req->complete = gs_setup_complete;
-
- switch (ctrl->bRequestType & USB_TYPE_MASK) {
- case USB_TYPE_STANDARD:
- ret = gs_setup_standard(gadget, ctrl);
- break;
-
- case USB_TYPE_CLASS:
- ret = gs_setup_class(gadget, ctrl);
- break;
-
- default:
- pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
- "value=%04x, index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- wValue, wIndex, wLength);
- break;
- }
-
- /* respond with data transfer before status phase? */
- if (ret >= 0) {
- req->length = ret;
- req->zero = ret < wLength
- && (ret % gadget->ep0->maxpacket) == 0;
- ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
- if (ret < 0) {
- pr_err("gs_setup: cannot queue response, ret=%d\n",
- ret);
- req->status = 0;
- gs_setup_complete(gadget->ep0, req);
- }
- }
-
- /* device either stalls (ret < 0) or reports success */
- return ret;
-}
-
-/*
- * gs_disconnect
- *
- * Called when the device is disconnected. Frees the closed
- * ports and disconnects open ports. Open ports will be freed
- * on close. Then reallocates the ports for the next connection.
- */
-static void gs_disconnect(struct usb_gadget *gadget)
-{
- unsigned long flags;
- struct gs_dev *dev = get_gadget_data(gadget);
-
- spin_lock_irqsave(&dev->dev_lock, flags);
-
- gs_reset_config(dev);
-
- /* free closed ports and disconnect open ports */
- /* (open ports will be freed when closed) */
- gs_free_ports(dev);
-
- /* re-allocate ports for the next connection */
- if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
- pr_err("gs_disconnect: cannot re-allocate ports\n");
-
- spin_unlock_irqrestore(&dev->dev_lock, flags);
-
- pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
-}
-
-static struct usb_gadget_driver gs_gadget_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- .speed = USB_SPEED_HIGH,
-#else
- .speed = USB_SPEED_FULL,
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
- .function = GS_LONG_NAME,
- .bind = gs_bind,
- .unbind = gs_unbind,
- .setup = gs_setup,
- .disconnect = gs_disconnect,
- .driver = {
- .name = GS_SHORT_NAME,
- .owner = THIS_MODULE,
- },
+static struct usb_composite_driver gserial_driver = {
+ .name = "g_serial",
+ .dev = &device_desc,
+ .strings = dev_strings,
+ .bind = gs_bind,
};
-/*
- * gs_set_config
- *
- * Configures the device by enabling device specific
- * optimizations, setting up the endpoints, allocating
- * read and write requests and queuing read requests.
- *
- * The device lock must be held when calling this function.
- */
-static int gs_set_config(struct gs_dev *dev, unsigned config)
+static int __init init(void)
{
- int i;
- int ret = 0;
- struct usb_gadget *gadget = dev->dev_gadget;
- struct usb_ep *ep;
- struct usb_endpoint_descriptor *out, *in, *notify;
- struct usb_request *req;
-
- if (dev == NULL) {
- pr_err("gs_set_config: NULL device pointer\n");
- return 0;
- }
-
- if (config == dev->dev_config)
- return 0;
-
- gs_reset_config(dev);
-
- switch (config) {
- case GS_NO_CONFIG_ID:
- return 0;
- case GS_BULK_CONFIG_ID:
- if (use_acm)
- return -EINVAL;
- break;
- case GS_ACM_CONFIG_ID:
- if (!use_acm)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
-
- in = choose_ep_desc(gadget,
- &gs_highspeed_in_desc,
- &gs_fullspeed_in_desc);
- out = choose_ep_desc(gadget,
- &gs_highspeed_out_desc,
- &gs_fullspeed_out_desc);
- notify = dev->dev_notify_ep
- ? choose_ep_desc(gadget,
- &gs_highspeed_notify_desc,
- &gs_fullspeed_notify_desc)
- : NULL;
-
- ret = usb_ep_enable(dev->dev_in_ep, in);
- if (ret == 0) {
- dev->dev_in_ep_desc = in;
- } else {
- pr_debug("%s: cannot enable %s %s, ret=%d\n",
- __func__, "IN", dev->dev_in_ep->name, ret);
- return ret;
- }
-
- ret = usb_ep_enable(dev->dev_out_ep, out);
- if (ret == 0) {
- dev->dev_out_ep_desc = out;
- } else {
- pr_debug("%s: cannot enable %s %s, ret=%d\n",
- __func__, "OUT", dev->dev_out_ep->name, ret);
-fail0:
- usb_ep_disable(dev->dev_in_ep);
- return ret;
- }
-
- if (notify) {
- ret = usb_ep_enable(dev->dev_notify_ep, notify);
- if (ret == 0) {
- dev->dev_notify_ep_desc = notify;
- } else {
- pr_debug("%s: cannot enable %s %s, ret=%d\n",
- __func__, "NOTIFY",
- dev->dev_notify_ep->name, ret);
- usb_ep_disable(dev->dev_out_ep);
- goto fail0;
- }
- }
-
- dev->dev_config = config;
-
- /* allocate and queue read requests */
- ep = dev->dev_out_ep;
- for (i=0; i<read_q_size && ret == 0; i++) {
- if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
- req->complete = gs_read_complete;
- if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
- pr_err("gs_set_config: cannot queue read "
- "request, ret=%d\n", ret);
- }
- } else {
- pr_err("gs_set_config: cannot allocate "
- "read requests\n");
- ret = -ENOMEM;
- goto exit_reset_config;
- }
- }
-
- /* allocate write requests, and put on free list */
- ep = dev->dev_in_ep;
- for (i=0; i<write_q_size; i++) {
- req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
- if (req) {
- req->complete = gs_write_complete;
- list_add(&req->list, &dev->dev_req_list);
- } else {
- pr_err("gs_set_config: cannot allocate "
- "write requests\n");
- ret = -ENOMEM;
- goto exit_reset_config;
- }
- }
-
- /* REVISIT the ACM mode should be able to actually *issue* some
- * notifications, for at least serial state change events if
- * not also for network connection; say so in bmCapabilities.
+ /* We *could* export two configs; that'd be much cleaner...
+ * but neither of these product IDs was defined that way.
*/
-
- pr_info("gs_set_config: %s configured, %s speed %s config\n",
- GS_LONG_NAME,
- gadget->speed == USB_SPEED_HIGH ? "high" : "full",
- config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
-
- return 0;
-
-exit_reset_config:
- gs_reset_config(dev);
- return ret;
-}
-
-/*
- * gs_reset_config
- *
- * Mark the device as not configured, disable all endpoints,
- * which forces completion of pending I/O and frees queued
- * requests, and free the remaining write requests on the
- * free list.
- *
- * The device lock must be held when calling this function.
- */
-static void gs_reset_config(struct gs_dev *dev)
-{
- struct usb_request *req;
-
- if (dev == NULL) {
- pr_err("gs_reset_config: NULL device pointer\n");
- return;
- }
-
- if (dev->dev_config == GS_NO_CONFIG_ID)
- return;
-
- dev->dev_config = GS_NO_CONFIG_ID;
-
- /* free write requests on the free list */
- while(!list_empty(&dev->dev_req_list)) {
- req = list_entry(dev->dev_req_list.next,
- struct usb_request, list);
- list_del(&req->list);
- gs_free_req(dev->dev_in_ep, req);
- }
-
- /* disable endpoints, forcing completion of pending i/o; */
- /* completion handlers free their requests in this case */
- if (dev->dev_notify_ep)
- usb_ep_disable(dev->dev_notify_ep);
- usb_ep_disable(dev->dev_in_ep);
- usb_ep_disable(dev->dev_out_ep);
-}
-
-/*
- * gs_build_config_buf
- *
- * Builds the config descriptors in the given buffer and returns the
- * length, or a negative error number.
- */
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
- u8 type, unsigned int index, int is_otg)
-{
- int len;
- int high_speed = 0;
- const struct usb_config_descriptor *config_desc;
- const struct usb_descriptor_header **function;
-
- if (index >= gs_device_desc.bNumConfigurations)
- return -EINVAL;
-
- /* other speed switches high and full speed */
- if (gadget_is_dualspeed(g)) {
- high_speed = (g->speed == USB_SPEED_HIGH);
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- high_speed = !high_speed;
- }
-
if (use_acm) {
- config_desc = &gs_acm_config_desc;
- function = high_speed
- ? gs_acm_highspeed_function
- : gs_acm_fullspeed_function;
+ serial_config_driver.label = "CDC ACM config";
+ serial_config_driver.bConfigurationValue = 2;
+ device_desc.bDeviceClass = USB_CLASS_COMM;
+ device_desc.idProduct =
+ __constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
} else {
- config_desc = &gs_bulk_config_desc;
- function = high_speed
- ? gs_bulk_highspeed_function
- : gs_bulk_fullspeed_function;
- }
-
- /* for now, don't advertise srp-only devices */
- if (!is_otg)
- function++;
-
- len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function);
- if (len < 0)
- return len;
-
- ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
-
- return len;
-}
-
-/*
- * gs_alloc_req
- *
- * Allocate a usb_request and its buffer. Returns a pointer to the
- * usb_request or NULL if there is an error.
- */
-static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
-{
- struct usb_request *req;
-
- if (ep == NULL)
- return NULL;
-
- req = usb_ep_alloc_request(ep, kmalloc_flags);
-
- if (req != NULL) {
- req->length = len;
- req->buf = kmalloc(len, kmalloc_flags);
- if (req->buf == NULL) {
- usb_ep_free_request(ep, req);
- return NULL;
- }
+ serial_config_driver.label = "Generic Serial config";
+ serial_config_driver.bConfigurationValue = 1;
+ device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+ device_desc.idProduct =
+ __constant_cpu_to_le16(GS_PRODUCT_ID);
}
+ strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
- return req;
+ return usb_composite_register(&gserial_driver);
}
+module_init(init);
-/*
- * gs_free_req
- *
- * Free a usb_request and its buffer.
- */
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+static void __exit cleanup(void)
{
- if (ep != NULL && req != NULL) {
- kfree(req->buf);
- usb_ep_free_request(ep, req);
- }
-}
-
-/*
- * gs_alloc_ports
- *
- * Allocate all ports and set the gs_dev struct to point to them.
- * Return 0 if successful, or a negative error number.
- *
- * The device lock is normally held when calling this function.
- */
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
-{
- int i;
- struct gs_port *port;
-
- if (dev == NULL)
- return -EIO;
-
- for (i=0; i<GS_NUM_PORTS; i++) {
- if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
- return -ENOMEM;
-
- port->port_dev = dev;
- port->port_num = i;
- port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
- port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
- port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
- port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
- spin_lock_init(&port->port_lock);
- init_waitqueue_head(&port->port_write_wait);
-
- dev->dev_port[i] = port;
- }
-
- return 0;
-}
-
-/*
- * gs_free_ports
- *
- * Free all closed ports. Open ports are disconnected by
- * freeing their write buffers, setting their device pointers
- * and the pointers to them in the device to NULL. These
- * ports will be freed when closed.
- *
- * The device lock is normally held when calling this function.
- */
-static void gs_free_ports(struct gs_dev *dev)
-{
- int i;
- unsigned long flags;
- struct gs_port *port;
-
- if (dev == NULL)
- return;
-
- for (i=0; i<GS_NUM_PORTS; i++) {
- if ((port=dev->dev_port[i]) != NULL) {
- dev->dev_port[i] = NULL;
-
- spin_lock_irqsave(&port->port_lock, flags);
-
- if (port->port_write_buf != NULL) {
- gs_buf_free(port->port_write_buf);
- port->port_write_buf = NULL;
- }
-
- if (port->port_open_count > 0 || port->port_in_use) {
- port->port_dev = NULL;
- wake_up_interruptible(&port->port_write_wait);
- if (port->port_tty) {
- tty_hangup(port->port_tty);
- }
- spin_unlock_irqrestore(&port->port_lock, flags);
- } else {
- spin_unlock_irqrestore(&port->port_lock, flags);
- kfree(port);
- }
-
- }
- }
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Circular Buffer */
-
-/*
- * gs_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
-{
- struct gs_buf *gb;
-
- if (size == 0)
- return NULL;
-
- gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
- if (gb == NULL)
- return NULL;
-
- gb->buf_buf = kmalloc(size, kmalloc_flags);
- if (gb->buf_buf == NULL) {
- kfree(gb);
- return NULL;
- }
-
- gb->buf_size = size;
- gb->buf_get = gb->buf_put = gb->buf_buf;
-
- return gb;
-}
-
-/*
- * gs_buf_free
- *
- * Free the buffer and all associated memory.
- */
-static void gs_buf_free(struct gs_buf *gb)
-{
- if (gb) {
- kfree(gb->buf_buf);
- kfree(gb);
- }
-}
-
-/*
- * gs_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-static void gs_buf_clear(struct gs_buf *gb)
-{
- if (gb != NULL)
- gb->buf_get = gb->buf_put;
- /* equivalent to a get of all data available */
-}
-
-/*
- * gs_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-static unsigned int gs_buf_data_avail(struct gs_buf *gb)
-{
- if (gb != NULL)
- return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
- else
- return 0;
-}
-
-/*
- * gs_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-static unsigned int gs_buf_space_avail(struct gs_buf *gb)
-{
- if (gb != NULL)
- return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
- else
- return 0;
-}
-
-/*
- * gs_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-static unsigned int
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
-{
- unsigned int len;
-
- if (gb == NULL)
- return 0;
-
- len = gs_buf_space_avail(gb);
- if (count > len)
- count = len;
-
- if (count == 0)
- return 0;
-
- len = gb->buf_buf + gb->buf_size - gb->buf_put;
- if (count > len) {
- memcpy(gb->buf_put, buf, len);
- memcpy(gb->buf_buf, buf+len, count - len);
- gb->buf_put = gb->buf_buf + count - len;
- } else {
- memcpy(gb->buf_put, buf, count);
- if (count < len)
- gb->buf_put += count;
- else /* count == len */
- gb->buf_put = gb->buf_buf;
- }
-
- return count;
-}
-
-/*
- * gs_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-static unsigned int
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
-{
- unsigned int len;
-
- if (gb == NULL)
- return 0;
-
- len = gs_buf_data_avail(gb);
- if (count > len)
- count = len;
-
- if (count == 0)
- return 0;
-
- len = gb->buf_buf + gb->buf_size - gb->buf_get;
- if (count > len) {
- memcpy(buf, gb->buf_get, len);
- memcpy(buf+len, gb->buf_buf, count - len);
- gb->buf_get = gb->buf_buf + count - len;
- } else {
- memcpy(buf, gb->buf_get, count);
- if (count < len)
- gb->buf_get += count;
- else /* count == len */
- gb->buf_get = gb->buf_buf;
- }
-
- return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct tty_driver *gs_tty_driver;
-
-/*
- * gs_module_init
- *
- * Register as a USB gadget driver and a tty driver.
- */
-static int __init gs_module_init(void)
-{
- int i;
- int retval;
-
- retval = usb_gadget_register_driver(&gs_gadget_driver);
- if (retval) {
- pr_err("gs_module_init: cannot register gadget driver, "
- "ret=%d\n", retval);
- return retval;
- }
-
- gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);
- if (!gs_tty_driver)
- return -ENOMEM;
- gs_tty_driver->owner = THIS_MODULE;
- gs_tty_driver->driver_name = GS_SHORT_NAME;
- gs_tty_driver->name = "ttygs";
- gs_tty_driver->major = GS_MAJOR;
- gs_tty_driver->minor_start = GS_MINOR_START;
- gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- gs_tty_driver->init_termios = tty_std_termios;
- /* must match GS_DEFAULT_DTE_RATE and friends */
- gs_tty_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE;
- gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE;
- tty_set_operations(gs_tty_driver, &gs_tty_ops);
-
- for (i = 0; i < GS_NUM_PORTS; i++)
- mutex_init(&gs_open_close_lock[i]);
-
- retval = tty_register_driver(gs_tty_driver);
- if (retval) {
- usb_gadget_unregister_driver(&gs_gadget_driver);
- put_tty_driver(gs_tty_driver);
- pr_err("gs_module_init: cannot register tty driver, "
- "ret=%d\n", retval);
- return retval;
- }
-
- pr_info("gs_module_init: %s %s loaded\n",
- GS_LONG_NAME, GS_VERSION_STR);
- return 0;
-}
-module_init(gs_module_init);
-
-/*
- * gs_module_exit
- *
- * Unregister as a tty driver and a USB gadget driver.
- */
-static void __exit gs_module_exit(void)
-{
- tty_unregister_driver(gs_tty_driver);
- put_tty_driver(gs_tty_driver);
- usb_gadget_unregister_driver(&gs_gadget_driver);
-
- pr_info("gs_module_exit: %s %s unloaded\n",
- GS_LONG_NAME, GS_VERSION_STR);
+ usb_composite_unregister(&gserial_driver);
+ gserial_cleanup();
}
-module_exit(gs_module_exit);
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
new file mode 100644
index 00000000000..5458f43a866
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.c
@@ -0,0 +1,967 @@
+/*
+ * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This component encapsulates the Ethernet link glue needed to provide
+ * one (!) network link through the USB gadget stack, normally "usb0".
+ *
+ * The control and data models are handled by the function driver which
+ * connects to this code; such as CDC Ethernet, "CDC Subset", or RNDIS.
+ * That includes all descriptor and endpoint management.
+ *
+ * Link level addressing is handled by this component using module
+ * parameters; if no such parameters are provided, random link level
+ * addresses are used. Each end of the link uses one address. The
+ * host end address is exported in various ways, and is often recorded
+ * in configuration databases.
+ *
+ * The driver which assembles each configuration using such a link is
+ * responsible for ensuring that each configuration includes at most one
+ * instance of is network link. (The network layer provides ways for
+ * this single "physical" link to be used by multiple virtual links.)
+ */
+
+#define DRIVER_VERSION "29-May-2008"
+
+struct eth_dev {
+ /* lock is held while accessing port_usb
+ * or updating its backlink port_usb->ioport
+ */
+ spinlock_t lock;
+ struct gether *port_usb;
+
+ struct net_device *net;
+ struct usb_gadget *gadget;
+
+ spinlock_t req_lock; /* guard {rx,tx}_reqs */
+ struct list_head tx_reqs, rx_reqs;
+ atomic_t tx_qlen;
+
+ unsigned header_len;
+ struct sk_buff *(*wrap)(struct sk_buff *skb);
+ int (*unwrap)(struct sk_buff *skb);
+
+ struct work_struct work;
+
+ unsigned long todo;
+#define WORK_RX_MEMORY 0
+
+ bool zlp;
+ u8 host_mac[ETH_ALEN];
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define RX_EXTRA 20 /* bytes guarding against rx overflows */
+
+#define DEFAULT_QLEN 2 /* double buffering by default */
+
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+
+static unsigned qmult = 5;
+module_param(qmult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
+
+#else /* full speed (low speed doesn't do bulk) */
+#define qmult 1
+#endif
+
+/* for dual-speed hardware, use deeper queues at highspeed */
+static inline int qlen(struct usb_gadget *gadget)
+{
+ if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH)
+ return qmult * DEFAULT_QLEN;
+ else
+ return DEFAULT_QLEN;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* REVISIT there must be a better way than having two sets
+ * of debug calls ...
+ */
+
+#undef DBG
+#undef VDBG
+#undef ERROR
+#undef WARN
+#undef INFO
+
+#define xprintk(d, level, fmt, args...) \
+ printk(level "%s: " fmt , (d)->net->name , ## args)
+
+#ifdef DEBUG
+#undef DEBUG
+#define DBG(dev, fmt, args...) \
+ xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev, fmt, args...) \
+ do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE_DEBUG
+#define VDBG DBG
+#else
+#define VDBG(dev, fmt, args...) \
+ do { } while (0)
+#endif /* DEBUG */
+
+#define ERROR(dev, fmt, args...) \
+ xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev, fmt, args...) \
+ xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev, fmt, args...) \
+ xprintk(dev , KERN_INFO , fmt , ## args)
+
+/*-------------------------------------------------------------------------*/
+
+/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
+
+static int eth_change_mtu(struct net_device *net, int new_mtu)
+{
+ struct eth_dev *dev = netdev_priv(net);
+ unsigned long flags;
+ int status = 0;
+
+ /* don't change MTU on "live" link (peer won't know) */
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->port_usb)
+ status = -EBUSY;
+ else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+ status = -ERANGE;
+ else
+ net->mtu = new_mtu;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return status;
+}
+
+static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
+{
+ struct eth_dev *dev = netdev_priv(net);
+
+ strlcpy(p->driver, "g_ether", sizeof p->driver);
+ strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+ strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
+ strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
+}
+
+static u32 eth_get_link(struct net_device *net)
+{
+ struct eth_dev *dev = netdev_priv(net);
+ return dev->gadget->speed != USB_SPEED_UNKNOWN;
+}
+
+/* REVISIT can also support:
+ * - WOL (by tracking suspends and issuing remote wakeup)
+ * - msglevel (implies updated messaging)
+ * - ... probably more ethtool ops
+ */
+
+static struct ethtool_ops ops = {
+ .get_drvinfo = eth_get_drvinfo,
+ .get_link = eth_get_link
+};
+
+static void defer_kevent(struct eth_dev *dev, int flag)
+{
+ if (test_and_set_bit(flag, &dev->todo))
+ return;
+ if (!schedule_work(&dev->work))
+ ERROR(dev, "kevent %d may have been dropped\n", flag);
+ else
+ DBG(dev, "kevent %d scheduled\n", flag);
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+
+static int
+rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
+{
+ struct sk_buff *skb;
+ int retval = -ENOMEM;
+ size_t size = 0;
+ struct usb_ep *out;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->port_usb)
+ out = dev->port_usb->out_ep;
+ else
+ out = NULL;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (!out)
+ return -ENOTCONN;
+
+
+ /* Padding up to RX_EXTRA handles minor disagreements with host.
+ * Normally we use the USB "terminate on short read" convention;
+ * so allow up to (N*maxpacket), since that memory is normally
+ * already allocated. Some hardware doesn't deal well with short
+ * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
+ * byte off the end (to force hardware errors on overflow).
+ *
+ * RNDIS uses internal framing, and explicitly allows senders to
+ * pad to end-of-packet. That's potentially nice for speed, but
+ * means receivers can't recover lost synch on their own (because
+ * new packets don't only start after a short RX).
+ */
+ size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
+ size += dev->port_usb->header_len;
+ size += out->maxpacket - 1;
+ size -= size % out->maxpacket;
+
+ skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
+ if (skb == NULL) {
+ DBG(dev, "no rx skb\n");
+ goto enomem;
+ }
+
+ /* Some platforms perform better when IP packets are aligned,
+ * but on at least one, checksumming fails otherwise. Note:
+ * RNDIS headers involve variable numbers of LE32 values.
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ req->buf = skb->data;
+ req->length = size;
+ req->complete = rx_complete;
+ req->context = skb;
+
+ retval = usb_ep_queue(out, req, gfp_flags);
+ if (retval == -ENOMEM)
+enomem:
+ defer_kevent(dev, WORK_RX_MEMORY);
+ if (retval) {
+ DBG(dev, "rx submit --> %d\n", retval);
+ if (skb)
+ dev_kfree_skb_any(skb);
+ spin_lock_irqsave(&dev->req_lock, flags);
+ list_add(&req->list, &dev->rx_reqs);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+ }
+ return retval;
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct sk_buff *skb = req->context;
+ struct eth_dev *dev = ep->driver_data;
+ int status = req->status;
+
+ switch (status) {
+
+ /* normal completion */
+ case 0:
+ skb_put(skb, req->actual);
+ if (dev->unwrap)
+ status = dev->unwrap(skb);
+ if (status < 0
+ || ETH_HLEN > skb->len
+ || skb->len > ETH_FRAME_LEN) {
+ dev->net->stats.rx_errors++;
+ dev->net->stats.rx_length_errors++;
+ DBG(dev, "rx length %d\n", skb->len);
+ break;
+ }
+
+ skb->protocol = eth_type_trans(skb, dev->net);
+ dev->net->stats.rx_packets++;
+ dev->net->stats.rx_bytes += skb->len;
+
+ /* no buffer copies needed, unless hardware can't
+ * use skb buffers.
+ */
+ status = netif_rx(skb);
+ skb = NULL;
+ break;
+
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* unlink */
+ case -ESHUTDOWN: /* disconnect etc */
+ VDBG(dev, "rx shutdown, code %d\n", status);
+ goto quiesce;
+
+ /* for hardware automagic (such as pxa) */
+ case -ECONNABORTED: /* endpoint reset */
+ DBG(dev, "rx %s reset\n", ep->name);
+ defer_kevent(dev, WORK_RX_MEMORY);
+quiesce:
+ dev_kfree_skb_any(skb);
+ goto clean;
+
+ /* data overrun */
+ case -EOVERFLOW:
+ dev->net->stats.rx_over_errors++;
+ /* FALLTHROUGH */
+
+ default:
+ dev->net->stats.rx_errors++;
+ DBG(dev, "rx status %d\n", status);
+ break;
+ }
+
+ if (skb)
+ dev_kfree_skb_any(skb);
+ if (!netif_running(dev->net)) {
+clean:
+ spin_lock(&dev->req_lock);
+ list_add(&req->list, &dev->rx_reqs);
+ spin_unlock(&dev->req_lock);
+ req = NULL;
+ }
+ if (req)
+ rx_submit(dev, req, GFP_ATOMIC);
+}
+
+static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
+{
+ unsigned i;
+ struct usb_request *req;
+
+ if (!n)
+ return -ENOMEM;
+
+ /* queue/recycle up to N requests */
+ i = n;
+ list_for_each_entry(req, list, list) {
+ if (i-- == 0)
+ goto extra;
+ }
+ while (i--) {
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+ if (!req)
+ return list_empty(list) ? -ENOMEM : 0;
+ list_add(&req->list, list);
+ }
+ return 0;
+
+extra:
+ /* free extras */
+ for (;;) {
+ struct list_head *next;
+
+ next = req->list.next;
+ list_del(&req->list);
+ usb_ep_free_request(ep, req);
+
+ if (next == list)
+ break;
+
+ req = container_of(next, struct usb_request, list);
+ }
+ return 0;
+}
+
+static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
+{
+ int status;
+
+ spin_lock(&dev->req_lock);
+ status = prealloc(&dev->tx_reqs, link->in_ep, n);
+ if (status < 0)
+ goto fail;
+ status = prealloc(&dev->rx_reqs, link->out_ep, n);
+ if (status < 0)
+ goto fail;
+ goto done;
+fail:
+ DBG(dev, "can't alloc requests\n");
+done:
+ spin_unlock(&dev->req_lock);
+ return status;
+}
+
+static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
+{
+ struct usb_request *req;
+ unsigned long flags;
+
+ /* fill unused rxq slots with some skb */
+ spin_lock_irqsave(&dev->req_lock, flags);
+ while (!list_empty(&dev->rx_reqs)) {
+ req = container_of(dev->rx_reqs.next,
+ struct usb_request, list);
+ list_del_init(&req->list);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+
+ if (rx_submit(dev, req, gfp_flags) < 0) {
+ defer_kevent(dev, WORK_RX_MEMORY);
+ return;
+ }
+
+ spin_lock_irqsave(&dev->req_lock, flags);
+ }
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+}
+
+static void eth_work(struct work_struct *work)
+{
+ struct eth_dev *dev = container_of(work, struct eth_dev, work);
+
+ if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) {
+ if (netif_running(dev->net))
+ rx_fill(dev, GFP_KERNEL);
+ }
+
+ if (dev->todo)
+ DBG(dev, "work done, flags = 0x%lx\n", dev->todo);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct sk_buff *skb = req->context;
+ struct eth_dev *dev = ep->driver_data;
+
+ switch (req->status) {
+ default:
+ dev->net->stats.tx_errors++;
+ VDBG(dev, "tx err %d\n", req->status);
+ /* FALLTHROUGH */
+ case -ECONNRESET: /* unlink */
+ case -ESHUTDOWN: /* disconnect etc */
+ break;
+ case 0:
+ dev->net->stats.tx_bytes += skb->len;
+ }
+ dev->net->stats.tx_packets++;
+
+ spin_lock(&dev->req_lock);
+ list_add(&req->list, &dev->tx_reqs);
+ spin_unlock(&dev->req_lock);
+ dev_kfree_skb_any(skb);
+
+ atomic_dec(&dev->tx_qlen);
+ if (netif_carrier_ok(dev->net))
+ netif_wake_queue(dev->net);
+}
+
+static inline int is_promisc(u16 cdc_filter)
+{
+ return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
+static int eth_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+ struct eth_dev *dev = netdev_priv(net);
+ int length = skb->len;
+ int retval;
+ struct usb_request *req = NULL;
+ unsigned long flags;
+ struct usb_ep *in;
+ u16 cdc_filter;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->port_usb) {
+ in = dev->port_usb->in_ep;
+ cdc_filter = dev->port_usb->cdc_filter;
+ } else {
+ in = NULL;
+ cdc_filter = 0;
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (!in) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ /* apply outgoing CDC or RNDIS filters */
+ if (!is_promisc(cdc_filter)) {
+ u8 *dest = skb->data;
+
+ if (is_multicast_ether_addr(dest)) {
+ u16 type;
+
+ /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+ * SET_ETHERNET_MULTICAST_FILTERS requests
+ */
+ if (is_broadcast_ether_addr(dest))
+ type = USB_CDC_PACKET_TYPE_BROADCAST;
+ else
+ type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+ if (!(cdc_filter & type)) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ }
+ /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+ }
+
+ spin_lock_irqsave(&dev->req_lock, flags);
+ /*
+ * this freelist can be empty if an interrupt triggered disconnect()
+ * and reconfigured the gadget (shutting down this queue) after the
+ * network stack decided to xmit but before we got the spinlock.
+ */
+ if (list_empty(&dev->tx_reqs)) {
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+ return 1;
+ }
+
+ req = container_of(dev->tx_reqs.next, struct usb_request, list);
+ list_del(&req->list);
+
+ /* temporarily stop TX queue when the freelist empties */
+ if (list_empty(&dev->tx_reqs))
+ netif_stop_queue(net);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+
+ /* no buffer copies needed, unless the network stack did it
+ * or the hardware can't use skb buffers.
+ * or there's not enough space for extra headers we need
+ */
+ if (dev->wrap) {
+ struct sk_buff *skb_new;
+
+ skb_new = dev->wrap(skb);
+ if (!skb_new)
+ goto drop;
+
+ dev_kfree_skb_any(skb);
+ skb = skb_new;
+ length = skb->len;
+ }
+ req->buf = skb->data;
+ req->context = skb;
+ req->complete = tx_complete;
+
+ /* use zlp framing on tx for strict CDC-Ether conformance,
+ * though any robust network rx path ignores extra padding.
+ * and some hardware doesn't like to write zlps.
+ */
+ req->zero = 1;
+ if (!dev->zlp && (length % in->maxpacket) == 0)
+ length++;
+
+ req->length = length;
+
+ /* throttle highspeed IRQ rate back slightly */
+ if (gadget_is_dualspeed(dev->gadget))
+ req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
+ ? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
+ : 0;
+
+ retval = usb_ep_queue(in, req, GFP_ATOMIC);
+ switch (retval) {
+ default:
+ DBG(dev, "tx queue err %d\n", retval);
+ break;
+ case 0:
+ net->trans_start = jiffies;
+ atomic_inc(&dev->tx_qlen);
+ }
+
+ if (retval) {
+drop:
+ dev->net->stats.tx_dropped++;
+ dev_kfree_skb_any(skb);
+ spin_lock_irqsave(&dev->req_lock, flags);
+ if (list_empty(&dev->tx_reqs))
+ netif_start_queue(net);
+ list_add(&req->list, &dev->tx_reqs);
+ spin_unlock_irqrestore(&dev->req_lock, flags);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
+{
+ DBG(dev, "%s\n", __func__);
+
+ /* fill the rx queue */
+ rx_fill(dev, gfp_flags);
+
+ /* and open the tx floodgates */
+ atomic_set(&dev->tx_qlen, 0);
+ netif_wake_queue(dev->net);
+}
+
+static int eth_open(struct net_device *net)
+{
+ struct eth_dev *dev = netdev_priv(net);
+ struct gether *link;
+
+ DBG(dev, "%s\n", __func__);
+ if (netif_carrier_ok(dev->net))
+ eth_start(dev, GFP_KERNEL);
+
+ spin_lock_irq(&dev->lock);
+ link = dev->port_usb;
+ if (link && link->open)
+ link->open(link);
+ spin_unlock_irq(&dev->lock);
+
+ return 0;
+}
+
+static int eth_stop(struct net_device *net)
+{
+ struct eth_dev *dev = netdev_priv(net);
+ unsigned long flags;
+
+ VDBG(dev, "%s\n", __func__);
+ netif_stop_queue(net);
+
+ DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
+ dev->net->stats.rx_packets, dev->net->stats.tx_packets,
+ dev->net->stats.rx_errors, dev->net->stats.tx_errors
+ );
+
+ /* ensure there are no more active requests */
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->port_usb) {
+ struct gether *link = dev->port_usb;
+
+ if (link->close)
+ link->close(link);
+
+ /* NOTE: we have no abort-queue primitive we could use
+ * to cancel all pending I/O. Instead, we disable then
+ * reenable the endpoints ... this idiom may leave toggle
+ * wrong, but that's a self-correcting error.
+ *
+ * REVISIT: we *COULD* just let the transfers complete at
+ * their own pace; the network stack can handle old packets.
+ * For the moment we leave this here, since it works.
+ */
+ usb_ep_disable(link->in_ep);
+ usb_ep_disable(link->out_ep);
+ if (netif_carrier_ok(net)) {
+ DBG(dev, "host still using in/out endpoints\n");
+ usb_ep_enable(link->in_ep, link->in);
+ usb_ep_enable(link->out_ep, link->out);
+ }
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *dev_addr;
+module_param(dev_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *host_addr;
+module_param(host_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
+
+
+static u8 __init nibble(unsigned char c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = toupper(c);
+ if (isxdigit(c))
+ return 10 + c - 'A';
+ return 0;
+}
+
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
+{
+ if (str) {
+ unsigned i;
+
+ for (i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if ((*str == '.') || (*str == ':'))
+ str++;
+ num = nibble(*str++) << 4;
+ num |= (nibble(*str++));
+ dev_addr [i] = num;
+ }
+ if (is_valid_ether_addr(dev_addr))
+ return 0;
+ }
+ random_ether_addr(dev_addr);
+ return 1;
+}
+
+static struct eth_dev *the_dev;
+
+
+/**
+ * gether_setup - initialize one ethernet-over-usb link
+ * @g: gadget to associated with these links
+ * @ethaddr: NULL, or a buffer in which the ethernet address of the
+ * host side of the link is recorded
+ * Context: may sleep
+ *
+ * This sets up the single network link that may be exported by a
+ * gadget driver using this framework. The link layer addresses are
+ * set up using module parameters.
+ *
+ * Returns negative errno, or zero on success
+ */
+int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+{
+ struct eth_dev *dev;
+ struct net_device *net;
+ int status;
+
+ if (the_dev)
+ return -EBUSY;
+
+ net = alloc_etherdev(sizeof *dev);
+ if (!net)
+ return -ENOMEM;
+
+ dev = netdev_priv(net);
+ spin_lock_init(&dev->lock);
+ spin_lock_init(&dev->req_lock);
+ INIT_WORK(&dev->work, eth_work);
+ INIT_LIST_HEAD(&dev->tx_reqs);
+ INIT_LIST_HEAD(&dev->rx_reqs);
+
+ /* network device setup */
+ dev->net = net;
+ strcpy(net->name, "usb%d");
+
+ if (get_ether_addr(dev_addr, net->dev_addr))
+ dev_warn(&g->dev,
+ "using random %s ethernet address\n", "self");
+ if (get_ether_addr(host_addr, dev->host_mac))
+ dev_warn(&g->dev,
+ "using random %s ethernet address\n", "host");
+
+ if (ethaddr)
+ memcpy(ethaddr, dev->host_mac, ETH_ALEN);
+
+ net->change_mtu = eth_change_mtu;
+ net->hard_start_xmit = eth_start_xmit;
+ net->open = eth_open;
+ net->stop = eth_stop;
+ /* watchdog_timeo, tx_timeout ... */
+ /* set_multicast_list */
+ SET_ETHTOOL_OPS(net, &ops);
+
+ /* two kinds of host-initiated state changes:
+ * - iff DATA transfer is active, carrier is "on"
+ * - tx queueing enabled if open *and* carrier is "on"
+ */
+ netif_stop_queue(net);
+ netif_carrier_off(net);
+
+ dev->gadget = g;
+ SET_NETDEV_DEV(net, &g->dev);
+
+ status = register_netdev(net);
+ if (status < 0) {
+ dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
+ free_netdev(net);
+ } else {
+ DECLARE_MAC_BUF(tmp);
+
+ INFO(dev, "MAC %s\n", print_mac(tmp, net->dev_addr));
+ INFO(dev, "HOST MAC %s\n", print_mac(tmp, dev->host_mac));
+
+ the_dev = dev;
+ }
+
+ return status;
+}
+
+/**
+ * gether_cleanup - remove Ethernet-over-USB device
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gether_setup().
+ */
+void gether_cleanup(void)
+{
+ if (!the_dev)
+ return;
+
+ unregister_netdev(the_dev->net);
+ free_netdev(the_dev->net);
+
+ /* assuming we used keventd, it must quiesce too */
+ flush_scheduled_work();
+
+ the_dev = NULL;
+}
+
+
+/**
+ * gether_connect - notify network layer that USB link is active
+ * @link: the USB link, set up with endpoints, descriptors matching
+ * current device speed, and any framing wrapper(s) set up.
+ * Context: irqs blocked
+ *
+ * This is called to activate endpoints and let the network layer know
+ * the connection is active ("carrier detect"). It may cause the I/O
+ * queues to open and start letting network packets flow, but will in
+ * any case activate the endpoints so that they respond properly to the
+ * USB host.
+ *
+ * Verify net_device pointer returned using IS_ERR(). If it doesn't
+ * indicate some error code (negative errno), ep->driver_data values
+ * have been overwritten.
+ */
+struct net_device *gether_connect(struct gether *link)
+{
+ struct eth_dev *dev = the_dev;
+ int result = 0;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ link->in_ep->driver_data = dev;
+ result = usb_ep_enable(link->in_ep, link->in);
+ if (result != 0) {
+ DBG(dev, "enable %s --> %d\n",
+ link->in_ep->name, result);
+ goto fail0;
+ }
+
+ link->out_ep->driver_data = dev;
+ result = usb_ep_enable(link->out_ep, link->out);
+ if (result != 0) {
+ DBG(dev, "enable %s --> %d\n",
+ link->out_ep->name, result);
+ goto fail1;
+ }
+
+ if (result == 0)
+ result = alloc_requests(dev, link, qlen(dev->gadget));
+
+ if (result == 0) {
+ dev->zlp = link->is_zlp_ok;
+ DBG(dev, "qlen %d\n", qlen(dev->gadget));
+
+ dev->header_len = link->header_len;
+ dev->unwrap = link->unwrap;
+ dev->wrap = link->wrap;
+
+ spin_lock(&dev->lock);
+ dev->port_usb = link;
+ link->ioport = dev;
+ spin_unlock(&dev->lock);
+
+ netif_carrier_on(dev->net);
+ if (netif_running(dev->net))
+ eth_start(dev, GFP_ATOMIC);
+
+ /* on error, disable any endpoints */
+ } else {
+ (void) usb_ep_disable(link->out_ep);
+fail1:
+ (void) usb_ep_disable(link->in_ep);
+ }
+fail0:
+ /* caller is responsible for cleanup on error */
+ if (result < 0)
+ return ERR_PTR(result);
+ return dev->net;
+}
+
+/**
+ * gether_disconnect - notify network layer that USB link is inactive
+ * @link: the USB link, on which gether_connect() was called
+ * Context: irqs blocked
+ *
+ * This is called to deactivate endpoints and let the network layer know
+ * the connection went inactive ("no carrier").
+ *
+ * On return, the state is as if gether_connect() had never been called.
+ * The endpoints are inactive, and accordingly without active USB I/O.
+ * Pointers to endpoint descriptors and endpoint private data are nulled.
+ */
+void gether_disconnect(struct gether *link)
+{
+ struct eth_dev *dev = link->ioport;
+ struct usb_request *req;
+
+ WARN_ON(!dev);
+ if (!dev)
+ return;
+
+ DBG(dev, "%s\n", __func__);
+
+ netif_stop_queue(dev->net);
+ netif_carrier_off(dev->net);
+
+ /* disable endpoints, forcing (synchronous) completion
+ * of all pending i/o. then free the request objects
+ * and forget about the endpoints.
+ */
+ usb_ep_disable(link->in_ep);
+ spin_lock(&dev->req_lock);
+ while (!list_empty(&dev->tx_reqs)) {
+ req = container_of(dev->tx_reqs.next,
+ struct usb_request, list);
+ list_del(&req->list);
+
+ spin_unlock(&dev->req_lock);
+ usb_ep_free_request(link->in_ep, req);
+ spin_lock(&dev->req_lock);
+ }
+ spin_unlock(&dev->req_lock);
+ link->in_ep->driver_data = NULL;
+ link->in = NULL;
+
+ usb_ep_disable(link->out_ep);
+ spin_lock(&dev->req_lock);
+ while (!list_empty(&dev->rx_reqs)) {
+ req = container_of(dev->rx_reqs.next,
+ struct usb_request, list);
+ list_del(&req->list);
+
+ spin_unlock(&dev->req_lock);
+ usb_ep_free_request(link->out_ep, req);
+ spin_lock(&dev->req_lock);
+ }
+ spin_unlock(&dev->req_lock);
+ link->out_ep->driver_data = NULL;
+ link->out = NULL;
+
+ /* finish forgetting about this USB link episode */
+ dev->header_len = 0;
+ dev->unwrap = NULL;
+ dev->wrap = NULL;
+
+ spin_lock(&dev->lock);
+ dev->port_usb = NULL;
+ link->ioport = NULL;
+ spin_unlock(&dev->lock);
+}
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
new file mode 100644
index 00000000000..0d1f7ae3b07
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.h
@@ -0,0 +1,127 @@
+/*
+ * u_ether.h -- interface to USB gadget "ethernet link" utilities
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __U_ETHER_H
+#define __U_ETHER_H
+
+#include <linux/err.h>
+#include <linux/if_ether.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+#include "gadget_chips.h"
+
+
+/*
+ * This represents the USB side of an "ethernet" link, managed by a USB
+ * function which provides control and (maybe) framing. Two functions
+ * in different configurations could share the same ethernet link/netdev,
+ * using different host interaction models.
+ *
+ * There is a current limitation that only one instance of this link may
+ * be present in any given configuration. When that's a problem, network
+ * layer facilities can be used to package multiple logical links on this
+ * single "physical" one.
+ */
+struct gether {
+ struct usb_function func;
+
+ /* updated by gether_{connect,disconnect} */
+ struct eth_dev *ioport;
+
+ /* endpoints handle full and/or high speeds */
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep;
+
+ /* descriptors match device speed at gether_connect() time */
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+
+ bool is_zlp_ok;
+
+ u16 cdc_filter;
+
+ /* hooks for added framing, as needed for RNDIS and EEM.
+ * we currently don't support multiple frames per SKB.
+ */
+ u32 header_len;
+ struct sk_buff *(*wrap)(struct sk_buff *skb);
+ int (*unwrap)(struct sk_buff *skb);
+
+ /* called on network open/close */
+ void (*open)(struct gether *);
+ void (*close)(struct gether *);
+};
+
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* netdev setup/teardown as directed by the gadget driver */
+int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]);
+void gether_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+struct net_device *gether_connect(struct gether *);
+void gether_disconnect(struct gether *);
+
+/* Some controllers can't support CDC Ethernet (ECM) ... */
+static inline bool can_support_ecm(struct usb_gadget *gadget)
+{
+ if (!gadget_supports_altsettings(gadget))
+ return false;
+
+ /* SA1100 can do ECM, *without* status endpoint ... but we'll
+ * only use it in non-ECM mode for backwards compatibility
+ * (and since we currently require a status endpoint)
+ */
+ if (gadget_is_sa1100(gadget))
+ return false;
+
+ /* Everything else is *presumably* fine ... but this is a bit
+ * chancy, so be **CERTAIN** there are no hardware issues with
+ * your controller. Add it above if it can't handle CDC.
+ */
+ return true;
+}
+
+/* each configuration may bind one instance of an ethernet link */
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#ifdef CONFIG_USB_ETH_RNDIS
+
+int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#else
+
+static inline int
+rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+ return 0;
+}
+
+#endif
+
+#endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
new file mode 100644
index 00000000000..abf9505d3a7
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.c
@@ -0,0 +1,1246 @@
+/*
+ * u_serial.c - utilities for USB gadget "serial port"/TTY support
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This code also borrows from usbserial.c, which is
+ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
+ * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include "u_serial.h"
+
+
+/*
+ * This component encapsulates the TTY layer glue needed to provide basic
+ * "serial port" functionality through the USB gadget stack. Each such
+ * port is exposed through a /dev/ttyGS* node.
+ *
+ * After initialization (gserial_setup), these TTY port devices stay
+ * available until they are removed (gserial_cleanup). Each one may be
+ * connected to a USB function (gserial_connect), or disconnected (with
+ * gserial_disconnect) when the USB host issues a config change event.
+ * Data can only flow when the port is connected to the host.
+ *
+ * A given TTY port can be made available in multiple configurations.
+ * For example, each one might expose a ttyGS0 node which provides a
+ * login application. In one case that might use CDC ACM interface 0,
+ * while another configuration might use interface 3 for that. The
+ * work to handle that (including descriptor management) is not part
+ * of this component.
+ *
+ * Configurations may expose more than one TTY port. For example, if
+ * ttyGS0 provides login service, then ttyGS1 might provide dialer access
+ * for a telephone or fax link. And ttyGS2 might be something that just
+ * needs a simple byte stream interface for some messaging protocol that
+ * is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
+ */
+
+/*
+ * gserial is the lifecycle interface, used by USB functions
+ * gs_port is the I/O nexus, used by the tty driver
+ * tty_struct links to the tty/filesystem framework
+ *
+ * gserial <---> gs_port ... links will be null when the USB link is
+ * inactive; managed by gserial_{connect,disconnect}().
+ * gserial->ioport == usb_ep->driver_data ... gs_port
+ * gs_port->port_usb ... gserial
+ *
+ * gs_port <---> tty_struct ... links will be null when the TTY file
+ * isn't opened; managed by gs_open()/gs_close()
+ * gserial->port_tty ... tty_struct
+ * tty_struct->driver_data ... gserial
+ */
+
+/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the
+ * next layer of buffering. For TX that's a circular buffer; for RX
+ * consider it a NOP. A third layer is provided by the TTY code.
+ */
+#define QUEUE_SIZE 16
+#define WRITE_BUF_SIZE 8192 /* TX only */
+
+/* circular buffer */
+struct gs_buf {
+ unsigned buf_size;
+ char *buf_buf;
+ char *buf_get;
+ char *buf_put;
+};
+
+/*
+ * The port structure holds info for each port, one for each minor number
+ * (and thus for each /dev/ node).
+ */
+struct gs_port {
+ spinlock_t port_lock; /* guard port_* access */
+
+ struct gserial *port_usb;
+ struct tty_struct *port_tty;
+
+ unsigned open_count;
+ bool openclose; /* open/close in progress */
+ u8 port_num;
+
+ wait_queue_head_t close_wait; /* wait for last close */
+
+ struct list_head read_pool;
+ struct tasklet_struct push;
+
+ struct list_head write_pool;
+ struct gs_buf port_write_buf;
+ wait_queue_head_t drain_wait; /* wait while writes drain */
+
+ /* REVISIT this state ... */
+ struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
+};
+
+/* increase N_PORTS if you need more */
+#define N_PORTS 4
+static struct portmaster {
+ struct mutex lock; /* protect open/close */
+ struct gs_port *port;
+} ports[N_PORTS];
+static unsigned n_ports;
+
+#define GS_CLOSE_TIMEOUT 15 /* seconds */
+
+
+
+#ifdef VERBOSE_DEBUG
+#define pr_vdebug(fmt, arg...) \
+ pr_debug(fmt, ##arg)
+#else
+#define pr_vdebug(fmt, arg...) \
+ ({ if (0) pr_debug(fmt, ##arg); })
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Circular Buffer */
+
+/*
+ * gs_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
+{
+ gb->buf_buf = kmalloc(size, GFP_KERNEL);
+ if (gb->buf_buf == NULL)
+ return -ENOMEM;
+
+ gb->buf_size = size;
+ gb->buf_put = gb->buf_buf;
+ gb->buf_get = gb->buf_buf;
+
+ return 0;
+}
+
+/*
+ * gs_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void gs_buf_free(struct gs_buf *gb)
+{
+ kfree(gb->buf_buf);
+ gb->buf_buf = NULL;
+}
+
+/*
+ * gs_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void gs_buf_clear(struct gs_buf *gb)
+{
+ gb->buf_get = gb->buf_put;
+ /* equivalent to a get of all data available */
+}
+
+/*
+ * gs_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned gs_buf_data_avail(struct gs_buf *gb)
+{
+ return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
+}
+
+/*
+ * gs_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned gs_buf_space_avail(struct gs_buf *gb)
+{
+ return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
+}
+
+/*
+ * gs_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
+{
+ unsigned len;
+
+ len = gs_buf_space_avail(gb);
+ if (count > len)
+ count = len;
+
+ if (count == 0)
+ return 0;
+
+ len = gb->buf_buf + gb->buf_size - gb->buf_put;
+ if (count > len) {
+ memcpy(gb->buf_put, buf, len);
+ memcpy(gb->buf_buf, buf+len, count - len);
+ gb->buf_put = gb->buf_buf + count - len;
+ } else {
+ memcpy(gb->buf_put, buf, count);
+ if (count < len)
+ gb->buf_put += count;
+ else /* count == len */
+ gb->buf_put = gb->buf_buf;
+ }
+
+ return count;
+}
+
+/*
+ * gs_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
+{
+ unsigned len;
+
+ len = gs_buf_data_avail(gb);
+ if (count > len)
+ count = len;
+
+ if (count == 0)
+ return 0;
+
+ len = gb->buf_buf + gb->buf_size - gb->buf_get;
+ if (count > len) {
+ memcpy(buf, gb->buf_get, len);
+ memcpy(buf+len, gb->buf_buf, count - len);
+ gb->buf_get = gb->buf_buf + count - len;
+ } else {
+ memcpy(buf, gb->buf_get, count);
+ if (count < len)
+ gb->buf_get += count;
+ else /* count == len */
+ gb->buf_get = gb->buf_buf;
+ }
+
+ return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* I/O glue between TTY (upper) and USB function (lower) driver layers */
+
+/*
+ * gs_alloc_req
+ *
+ * Allocate a usb_request and its buffer. Returns a pointer to the
+ * usb_request or NULL if there is an error.
+ */
+static struct usb_request *
+gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
+{
+ struct usb_request *req;
+
+ req = usb_ep_alloc_request(ep, kmalloc_flags);
+
+ if (req != NULL) {
+ req->length = len;
+ req->buf = kmalloc(len, kmalloc_flags);
+ if (req->buf == NULL) {
+ usb_ep_free_request(ep, req);
+ return NULL;
+ }
+ }
+
+ return req;
+}
+
+/*
+ * gs_free_req
+ *
+ * Free a usb_request and its buffer.
+ */
+static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+{
+ kfree(req->buf);
+ usb_ep_free_request(ep, req);
+}
+
+/*
+ * gs_send_packet
+ *
+ * If there is data to send, a packet is built in the given
+ * buffer and the size is returned. If there is no data to
+ * send, 0 is returned.
+ *
+ * Called with port_lock held.
+ */
+static unsigned
+gs_send_packet(struct gs_port *port, char *packet, unsigned size)
+{
+ unsigned len;
+
+ len = gs_buf_data_avail(&port->port_write_buf);
+ if (len < size)
+ size = len;
+ if (size != 0)
+ size = gs_buf_get(&port->port_write_buf, packet, size);
+ return size;
+}
+
+/*
+ * gs_start_tx
+ *
+ * This function finds available write requests, calls
+ * gs_send_packet to fill these packets with data, and
+ * continues until either there are no more write requests
+ * available or no more data to send. This function is
+ * run whenever data arrives or write requests are available.
+ *
+ * Context: caller owns port_lock; port_usb is non-null.
+ */
+static int gs_start_tx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+ struct list_head *pool = &port->write_pool;
+ struct usb_ep *in = port->port_usb->in;
+ int status = 0;
+ bool do_tty_wake = false;
+
+ while (!list_empty(pool)) {
+ struct usb_request *req;
+ int len;
+
+ req = list_entry(pool->next, struct usb_request, list);
+ len = gs_send_packet(port, req->buf, in->maxpacket);
+ if (len == 0) {
+ wake_up_interruptible(&port->drain_wait);
+ break;
+ }
+ do_tty_wake = true;
+
+ req->length = len;
+ list_del(&req->list);
+
+#ifdef VERBOSE_DEBUG
+ pr_debug("%s: %s, len=%d, 0x%02x 0x%02x 0x%02x ...\n",
+ __func__, in->name, len, *((u8 *)req->buf),
+ *((u8 *)req->buf+1), *((u8 *)req->buf+2));
+#endif
+
+ /* Drop lock while we call out of driver; completions
+ * could be issued while we do so. Disconnection may
+ * happen too; maybe immediately before we queue this!
+ *
+ * NOTE that we may keep sending data for a while after
+ * the TTY closed (dev->ioport->port_tty is NULL).
+ */
+ spin_unlock(&port->port_lock);
+ status = usb_ep_queue(in, req, GFP_ATOMIC);
+ spin_lock(&port->port_lock);
+
+ if (status) {
+ pr_debug("%s: %s %s err %d\n",
+ __func__, "queue", in->name, status);
+ list_add(&req->list, pool);
+ break;
+ }
+
+ /* abort immediately after disconnect */
+ if (!port->port_usb)
+ break;
+ }
+
+ if (do_tty_wake && port->port_tty)
+ tty_wakeup(port->port_tty);
+ return status;
+}
+
+static void gs_rx_push(unsigned long _port)
+{
+ struct gs_port *port = (void *)_port;
+ struct tty_struct *tty = port->port_tty;
+
+ /* With low_latency, tty_flip_buffer_push() doesn't put its
+ * real work through a workqueue, so the ldisc has a better
+ * chance to keep up with peak USB data rates.
+ */
+ if (tty) {
+ tty_flip_buffer_push(tty);
+ wake_up_interruptible(&tty->read_wait);
+ }
+}
+
+/*
+ * gs_recv_packet
+ *
+ * Called for each USB packet received. Reads the packet
+ * header and stuffs the data in the appropriate tty buffer.
+ * Returns 0 if successful, or a negative error number.
+ *
+ * Called during USB completion routine, on interrupt time.
+ * With port_lock.
+ */
+static int gs_recv_packet(struct gs_port *port, char *packet, unsigned size)
+{
+ unsigned len;
+ struct tty_struct *tty;
+
+ /* I/O completions can continue for a while after close(), until the
+ * request queue empties. Just discard any data we receive, until
+ * something reopens this TTY ... as if there were no HW flow control.
+ */
+ tty = port->port_tty;
+ if (tty == NULL) {
+ pr_vdebug("%s: ttyGS%d, after close\n",
+ __func__, port->port_num);
+ return -EIO;
+ }
+
+ len = tty_insert_flip_string(tty, packet, size);
+ if (len > 0)
+ tasklet_schedule(&port->push);
+ if (len < size)
+ pr_debug("%s: ttyGS%d, drop %d bytes\n",
+ __func__, port->port_num, size - len);
+ return 0;
+}
+
+/*
+ * Context: caller owns port_lock, and port_usb is set
+ */
+static unsigned gs_start_rx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+ struct list_head *pool = &port->read_pool;
+ struct usb_ep *out = port->port_usb->out;
+ unsigned started = 0;
+
+ while (!list_empty(pool)) {
+ struct usb_request *req;
+ int status;
+ struct tty_struct *tty;
+
+ /* no more rx if closed or throttled */
+ tty = port->port_tty;
+ if (!tty || test_bit(TTY_THROTTLED, &tty->flags))
+ break;
+
+ req = list_entry(pool->next, struct usb_request, list);
+ list_del(&req->list);
+ req->length = out->maxpacket;
+
+ /* drop lock while we call out; the controller driver
+ * may need to call us back (e.g. for disconnect)
+ */
+ spin_unlock(&port->port_lock);
+ status = usb_ep_queue(out, req, GFP_ATOMIC);
+ spin_lock(&port->port_lock);
+
+ if (status) {
+ pr_debug("%s: %s %s err %d\n",
+ __func__, "queue", out->name, status);
+ list_add(&req->list, pool);
+ break;
+ }
+ started++;
+
+ /* abort immediately after disconnect */
+ if (!port->port_usb)
+ break;
+ }
+ return started;
+}
+
+static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ int status;
+ struct gs_port *port = ep->driver_data;
+
+ spin_lock(&port->port_lock);
+ list_add(&req->list, &port->read_pool);
+
+ switch (req->status) {
+ case 0:
+ /* normal completion */
+ status = gs_recv_packet(port, req->buf, req->actual);
+ if (status && status != -EIO)
+ pr_debug("%s: %s %s err %d\n",
+ __func__, "recv", ep->name, status);
+ gs_start_rx(port);
+ break;
+
+ case -ESHUTDOWN:
+ /* disconnect */
+ pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+ break;
+
+ default:
+ /* presumably a transient fault */
+ pr_warning("%s: unexpected %s status %d\n",
+ __func__, ep->name, req->status);
+ gs_start_rx(port);
+ break;
+ }
+ spin_unlock(&port->port_lock);
+}
+
+static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct gs_port *port = ep->driver_data;
+
+ spin_lock(&port->port_lock);
+ list_add(&req->list, &port->write_pool);
+
+ switch (req->status) {
+ default:
+ /* presumably a transient fault */
+ pr_warning("%s: unexpected %s status %d\n",
+ __func__, ep->name, req->status);
+ /* FALL THROUGH */
+ case 0:
+ /* normal completion */
+ gs_start_tx(port);
+ break;
+
+ case -ESHUTDOWN:
+ /* disconnect */
+ pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+ break;
+ }
+
+ spin_unlock(&port->port_lock);
+}
+
+static void gs_free_requests(struct usb_ep *ep, struct list_head *head)
+{
+ struct usb_request *req;
+
+ while (!list_empty(head)) {
+ req = list_entry(head->next, struct usb_request, list);
+ list_del(&req->list);
+ gs_free_req(ep, req);
+ }
+}
+
+static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
+ void (*fn)(struct usb_ep *, struct usb_request *))
+{
+ int i;
+ struct usb_request *req;
+
+ /* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
+ * do quite that many this time, don't fail ... we just won't
+ * be as speedy as we might otherwise be.
+ */
+ for (i = 0; i < QUEUE_SIZE; i++) {
+ req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
+ if (!req)
+ return list_empty(head) ? -ENOMEM : 0;
+ req->complete = fn;
+ list_add_tail(&req->list, head);
+ }
+ return 0;
+}
+
+/**
+ * gs_start_io - start USB I/O streams
+ * @dev: encapsulates endpoints to use
+ * Context: holding port_lock; port_tty and port_usb are non-null
+ *
+ * We only start I/O when something is connected to both sides of
+ * this port. If nothing is listening on the host side, we may
+ * be pointlessly filling up our TX buffers and FIFO.
+ */
+static int gs_start_io(struct gs_port *port)
+{
+ struct list_head *head = &port->read_pool;
+ struct usb_ep *ep = port->port_usb->out;
+ int status;
+ unsigned started;
+
+ /* Allocate RX and TX I/O buffers. We can't easily do this much
+ * earlier (with GFP_KERNEL) because the requests are coupled to
+ * endpoints, as are the packet sizes we'll be using. Different
+ * configurations may use different endpoints with a given port;
+ * and high speed vs full speed changes packet sizes too.
+ */
+ status = gs_alloc_requests(ep, head, gs_read_complete);
+ if (status)
+ return status;
+
+ status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
+ gs_write_complete);
+ if (status) {
+ gs_free_requests(ep, head);
+ return status;
+ }
+
+ /* queue read requests */
+ started = gs_start_rx(port);
+
+ /* unblock any pending writes into our circular buffer */
+ if (started) {
+ tty_wakeup(port->port_tty);
+ } else {
+ gs_free_requests(ep, head);
+ gs_free_requests(port->port_usb->in, &port->write_pool);
+ }
+
+ return started ? 0 : status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* TTY Driver */
+
+/*
+ * gs_open sets up the link between a gs_port and its associated TTY.
+ * That link is broken *only* by TTY close(), and all driver methods
+ * know that.
+ */
+static int gs_open(struct tty_struct *tty, struct file *file)
+{
+ int port_num = tty->index;
+ struct gs_port *port;
+ int status;
+
+ if (port_num < 0 || port_num >= n_ports)
+ return -ENXIO;
+
+ do {
+ mutex_lock(&ports[port_num].lock);
+ port = ports[port_num].port;
+ if (!port)
+ status = -ENODEV;
+ else {
+ spin_lock_irq(&port->port_lock);
+
+ /* already open? Great. */
+ if (port->open_count) {
+ status = 0;
+ port->open_count++;
+
+ /* currently opening/closing? wait ... */
+ } else if (port->openclose) {
+ status = -EBUSY;
+
+ /* ... else we do the work */
+ } else {
+ status = -EAGAIN;
+ port->openclose = true;
+ }
+ spin_unlock_irq(&port->port_lock);
+ }
+ mutex_unlock(&ports[port_num].lock);
+
+ switch (status) {
+ default:
+ /* fully handled */
+ return status;
+ case -EAGAIN:
+ /* must do the work */
+ break;
+ case -EBUSY:
+ /* wait for EAGAIN task to finish */
+ msleep(1);
+ /* REVISIT could have a waitchannel here, if
+ * concurrent open performance is important
+ */
+ break;
+ }
+ } while (status != -EAGAIN);
+
+ /* Do the "real open" */
+ spin_lock_irq(&port->port_lock);
+
+ /* allocate circular buffer on first open */
+ if (port->port_write_buf.buf_buf == NULL) {
+
+ spin_unlock_irq(&port->port_lock);
+ status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
+ spin_lock_irq(&port->port_lock);
+
+ if (status) {
+ pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
+ port->port_num, tty, file);
+ port->openclose = false;
+ goto exit_unlock_port;
+ }
+ }
+
+ /* REVISIT if REMOVED (ports[].port NULL), abort the open
+ * to let rmmod work faster (but this way isn't wrong).
+ */
+
+ /* REVISIT maybe wait for "carrier detect" */
+
+ tty->driver_data = port;
+ port->port_tty = tty;
+
+ port->open_count = 1;
+ port->openclose = false;
+
+ /* low_latency means ldiscs work in tasklet context, without
+ * needing a workqueue schedule ... easier to keep up.
+ */
+ tty->low_latency = 1;
+
+ /* if connected, start the I/O stream */
+ if (port->port_usb) {
+ pr_debug("gs_open: start ttyGS%d\n", port->port_num);
+ gs_start_io(port);
+
+ /* REVISIT for ACM, issue "network connected" event */
+ }
+
+ pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
+
+ status = 0;
+
+exit_unlock_port:
+ spin_unlock_irq(&port->port_lock);
+ return status;
+}
+
+static int gs_writes_finished(struct gs_port *p)
+{
+ int cond;
+
+ /* return true on disconnect or empty buffer */
+ spin_lock_irq(&p->port_lock);
+ cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
+ spin_unlock_irq(&p->port_lock);
+
+ return cond;
+}
+
+static void gs_close(struct tty_struct *tty, struct file *file)
+{
+ struct gs_port *port = tty->driver_data;
+
+ spin_lock_irq(&port->port_lock);
+
+ if (port->open_count != 1) {
+ if (port->open_count == 0)
+ WARN_ON(1);
+ else
+ --port->open_count;
+ goto exit;
+ }
+
+ pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
+
+ /* mark port as closing but in use; we can drop port lock
+ * and sleep if necessary
+ */
+ port->openclose = true;
+ port->open_count = 0;
+
+ if (port->port_usb)
+ /* REVISIT for ACM, issue "network disconnected" event */;
+
+ /* wait for circular write buffer to drain, disconnect, or at
+ * most GS_CLOSE_TIMEOUT seconds; then discard the rest
+ */
+ if (gs_buf_data_avail(&port->port_write_buf) > 0
+ && port->port_usb) {
+ spin_unlock_irq(&port->port_lock);
+ wait_event_interruptible_timeout(port->drain_wait,
+ gs_writes_finished(port),
+ GS_CLOSE_TIMEOUT * HZ);
+ spin_lock_irq(&port->port_lock);
+ }
+
+ /* Iff we're disconnected, there can be no I/O in flight so it's
+ * ok to free the circular buffer; else just scrub it. And don't
+ * let the push tasklet fire again until we're re-opened.
+ */
+ if (port->port_usb == NULL)
+ gs_buf_free(&port->port_write_buf);
+ else
+ gs_buf_clear(&port->port_write_buf);
+
+ tasklet_kill(&port->push);
+
+ tty->driver_data = NULL;
+ port->port_tty = NULL;
+
+ port->openclose = false;
+
+ pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
+ port->port_num, tty, file);
+
+ wake_up_interruptible(&port->close_wait);
+exit:
+ spin_unlock_irq(&port->port_lock);
+}
+
+static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+ int status;
+
+ pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
+ port->port_num, tty, count);
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (count)
+ count = gs_buf_put(&port->port_write_buf, buf, count);
+ /* treat count == 0 as flush_chars() */
+ if (port->port_usb)
+ status = gs_start_tx(port);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ return count;
+}
+
+static int gs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+ int status;
+
+ pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
+ port->port_num, tty, ch, __builtin_return_address(0));
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ status = gs_buf_put(&port->port_write_buf, &ch, 1);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ return status;
+}
+
+static void gs_flush_chars(struct tty_struct *tty)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+
+ pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (port->port_usb)
+ gs_start_tx(port);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int gs_write_room(struct tty_struct *tty)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+ int room = 0;
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (port->port_usb)
+ room = gs_buf_space_avail(&port->port_write_buf);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
+ port->port_num, tty, room);
+
+ return room;
+}
+
+static int gs_chars_in_buffer(struct tty_struct *tty)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+ int chars = 0;
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ chars = gs_buf_data_avail(&port->port_write_buf);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
+ port->port_num, tty, chars);
+
+ return chars;
+}
+
+/* undo side effects of setting TTY_THROTTLED */
+static void gs_unthrottle(struct tty_struct *tty)
+{
+ struct gs_port *port = tty->driver_data;
+ unsigned long flags;
+ unsigned started = 0;
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (port->port_usb)
+ started = gs_start_rx(port);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ pr_vdebug("gs_unthrottle: ttyGS%d, %d packets\n",
+ port->port_num, started);
+}
+
+static const struct tty_operations gs_tty_ops = {
+ .open = gs_open,
+ .close = gs_close,
+ .write = gs_write,
+ .put_char = gs_put_char,
+ .flush_chars = gs_flush_chars,
+ .write_room = gs_write_room,
+ .chars_in_buffer = gs_chars_in_buffer,
+ .unthrottle = gs_unthrottle,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct tty_driver *gs_tty_driver;
+
+static int __init
+gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
+{
+ struct gs_port *port;
+
+ port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
+ if (port == NULL)
+ return -ENOMEM;
+
+ spin_lock_init(&port->port_lock);
+ init_waitqueue_head(&port->close_wait);
+ init_waitqueue_head(&port->drain_wait);
+
+ tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
+
+ INIT_LIST_HEAD(&port->read_pool);
+ INIT_LIST_HEAD(&port->write_pool);
+
+ port->port_num = port_num;
+ port->port_line_coding = *coding;
+
+ ports[port_num].port = port;
+
+ return 0;
+}
+
+/**
+ * gserial_setup - initialize TTY driver for one or more ports
+ * @g: gadget to associate with these ports
+ * @count: how many ports to support
+ * Context: may sleep
+ *
+ * The TTY stack needs to know in advance how many devices it should
+ * plan to manage. Use this call to set up the ports you will be
+ * exporting through USB. Later, connect them to functions based
+ * on what configuration is activated by the USB host; and disconnect
+ * them as appropriate.
+ *
+ * An example would be a two-configuration device in which both
+ * configurations expose port 0, but through different functions.
+ * One configuration could even expose port 1 while the other
+ * one doesn't.
+ *
+ * Returns negative errno or zero.
+ */
+int __init gserial_setup(struct usb_gadget *g, unsigned count)
+{
+ unsigned i;
+ struct usb_cdc_line_coding coding;
+ int status;
+
+ if (count == 0 || count > N_PORTS)
+ return -EINVAL;
+
+ gs_tty_driver = alloc_tty_driver(count);
+ if (!gs_tty_driver)
+ return -ENOMEM;
+
+ gs_tty_driver->owner = THIS_MODULE;
+ gs_tty_driver->driver_name = "g_serial";
+ gs_tty_driver->name = "ttyGS";
+ /* uses dynamically assigned dev_t values */
+
+ gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+ gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ gs_tty_driver->init_termios = tty_std_termios;
+
+ /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
+ * MS-Windows. Otherwise, most of these flags shouldn't affect
+ * anything unless we were to actually hook up to a serial line.
+ */
+ gs_tty_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ gs_tty_driver->init_termios.c_ispeed = 9600;
+ gs_tty_driver->init_termios.c_ospeed = 9600;
+
+ coding.dwDTERate = __constant_cpu_to_le32(9600);
+ coding.bCharFormat = 8;
+ coding.bParityType = USB_CDC_NO_PARITY;
+ coding.bDataBits = USB_CDC_1_STOP_BITS;
+
+ tty_set_operations(gs_tty_driver, &gs_tty_ops);
+
+ /* make devices be openable */
+ for (i = 0; i < count; i++) {
+ mutex_init(&ports[i].lock);
+ status = gs_port_alloc(i, &coding);
+ if (status) {
+ count = i;
+ goto fail;
+ }
+ }
+ n_ports = count;
+
+ /* export the driver ... */
+ status = tty_register_driver(gs_tty_driver);
+ if (status) {
+ put_tty_driver(gs_tty_driver);
+ pr_err("%s: cannot register, err %d\n",
+ __func__, status);
+ goto fail;
+ }
+
+ /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
+ for (i = 0; i < count; i++) {
+ struct device *tty_dev;
+
+ tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
+ if (IS_ERR(tty_dev))
+ pr_warning("%s: no classdev for port %d, err %ld\n",
+ __func__, i, PTR_ERR(tty_dev));
+ }
+
+ pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
+ count, (count == 1) ? "" : "s");
+
+ return status;
+fail:
+ while (count--)
+ kfree(ports[count].port);
+ put_tty_driver(gs_tty_driver);
+ gs_tty_driver = NULL;
+ return status;
+}
+
+static int gs_closed(struct gs_port *port)
+{
+ int cond;
+
+ spin_lock_irq(&port->port_lock);
+ cond = (port->open_count == 0) && !port->openclose;
+ spin_unlock_irq(&port->port_lock);
+ return cond;
+}
+
+/**
+ * gserial_cleanup - remove TTY-over-USB driver and devices
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gserial_setup().
+ * Accordingly, it may need to wait until some open /dev/ files have
+ * closed.
+ *
+ * The caller must have issued @gserial_disconnect() for any ports
+ * that had previously been connected, so that there is never any
+ * I/O pending when it's called.
+ */
+void gserial_cleanup(void)
+{
+ unsigned i;
+ struct gs_port *port;
+
+ if (!gs_tty_driver)
+ return;
+
+ /* start sysfs and /dev/ttyGS* node removal */
+ for (i = 0; i < n_ports; i++)
+ tty_unregister_device(gs_tty_driver, i);
+
+ for (i = 0; i < n_ports; i++) {
+ /* prevent new opens */
+ mutex_lock(&ports[i].lock);
+ port = ports[i].port;
+ ports[i].port = NULL;
+ mutex_unlock(&ports[i].lock);
+
+ /* wait for old opens to finish */
+ wait_event(port->close_wait, gs_closed(port));
+
+ WARN_ON(port->port_usb != NULL);
+
+ kfree(port);
+ }
+ n_ports = 0;
+
+ tty_unregister_driver(gs_tty_driver);
+ gs_tty_driver = NULL;
+
+ pr_debug("%s: cleaned up ttyGS* support\n", __func__);
+}
+
+/**
+ * gserial_connect - notify TTY I/O glue that USB link is active
+ * @gser: the function, set up with endpoints and descriptors
+ * @port_num: which port is active
+ * Context: any (usually from irq)
+ *
+ * This is called activate endpoints and let the TTY layer know that
+ * the connection is active ... not unlike "carrier detect". It won't
+ * necessarily start I/O queues; unless the TTY is held open by any
+ * task, there would be no point. However, the endpoints will be
+ * activated so the USB host can perform I/O, subject to basic USB
+ * hardware flow control.
+ *
+ * Caller needs to have set up the endpoints and USB function in @dev
+ * before calling this, as well as the appropriate (speed-specific)
+ * endpoint descriptors, and also have set up the TTY driver by calling
+ * @gserial_setup().
+ *
+ * Returns negative errno or zero.
+ * On success, ep->driver_data will be overwritten.
+ */
+int gserial_connect(struct gserial *gser, u8 port_num)
+{
+ struct gs_port *port;
+ unsigned long flags;
+ int status;
+
+ if (!gs_tty_driver || port_num >= n_ports)
+ return -ENXIO;
+
+ /* we "know" gserial_cleanup() hasn't been called */
+ port = ports[port_num].port;
+
+ /* activate the endpoints */
+ status = usb_ep_enable(gser->in, gser->in_desc);
+ if (status < 0)
+ return status;
+ gser->in->driver_data = port;
+
+ status = usb_ep_enable(gser->out, gser->out_desc);
+ if (status < 0)
+ goto fail_out;
+ gser->out->driver_data = port;
+
+ /* then tell the tty glue that I/O can work */
+ spin_lock_irqsave(&port->port_lock, flags);
+ gser->ioport = port;
+ port->port_usb = gser;
+
+ /* REVISIT unclear how best to handle this state...
+ * we don't really couple it with the Linux TTY.
+ */
+ gser->port_line_coding = port->port_line_coding;
+
+ /* REVISIT if waiting on "carrier detect", signal. */
+
+ /* REVISIT for ACM, issue "network connection" status notification:
+ * connected if open_count, else disconnected.
+ */
+
+ /* if it's already open, start I/O */
+ if (port->open_count) {
+ pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
+ gs_start_io(port);
+ }
+
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ return status;
+
+fail_out:
+ usb_ep_disable(gser->in);
+ gser->in->driver_data = NULL;
+ return status;
+}
+
+/**
+ * gserial_disconnect - notify TTY I/O glue that USB link is inactive
+ * @gser: the function, on which gserial_connect() was called
+ * Context: any (usually from irq)
+ *
+ * This is called to deactivate endpoints and let the TTY layer know
+ * that the connection went inactive ... not unlike "hangup".
+ *
+ * On return, the state is as if gserial_connect() had never been called;
+ * there is no active USB I/O on these endpoints.
+ */
+void gserial_disconnect(struct gserial *gser)
+{
+ struct gs_port *port = gser->ioport;
+ unsigned long flags;
+
+ if (!port)
+ return;
+
+ /* tell the TTY glue not to do I/O here any more */
+ spin_lock_irqsave(&port->port_lock, flags);
+
+ /* REVISIT as above: how best to track this? */
+ port->port_line_coding = gser->port_line_coding;
+
+ port->port_usb = NULL;
+ gser->ioport = NULL;
+ if (port->open_count > 0 || port->openclose) {
+ wake_up_interruptible(&port->drain_wait);
+ if (port->port_tty)
+ tty_hangup(port->port_tty);
+ }
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
+ /* disable endpoints, aborting down any active I/O */
+ usb_ep_disable(gser->out);
+ gser->out->driver_data = NULL;
+
+ usb_ep_disable(gser->in);
+ gser->in->driver_data = NULL;
+
+ /* finally, free any unused/unusable I/O buffers */
+ spin_lock_irqsave(&port->port_lock, flags);
+ if (port->open_count == 0 && !port->openclose)
+ gs_buf_free(&port->port_write_buf);
+ gs_free_requests(gser->out, &port->read_pool);
+ gs_free_requests(gser->in, &port->write_pool);
+ spin_unlock_irqrestore(&port->port_lock, flags);
+}
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
new file mode 100644
index 00000000000..7b561138f90
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.h
@@ -0,0 +1,58 @@
+/*
+ * u_serial.h - interface to USB gadget "serial port"/TTY utilities
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#ifndef __U_SERIAL_H
+#define __U_SERIAL_H
+
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+/*
+ * One non-multiplexed "serial" I/O port ... there can be several of these
+ * on any given USB peripheral device, if it provides enough endpoints.
+ *
+ * The "u_serial" utility component exists to do one thing: manage TTY
+ * style I/O using the USB peripheral endpoints listed here, including
+ * hookups to sysfs and /dev for each logical "tty" device.
+ *
+ * REVISIT need TTY --> USB event flow too, so ACM can report open/close
+ * as carrier detect events. Model after ECM. There's more ACM state too.
+ *
+ * REVISIT someday, allow multiplexing several TTYs over these endpoints.
+ */
+struct gserial {
+ struct usb_function func;
+
+ /* port is managed by gserial_{connect,disconnect} */
+ struct gs_port *ioport;
+
+ struct usb_ep *in;
+ struct usb_ep *out;
+ struct usb_endpoint_descriptor *in_desc;
+ struct usb_endpoint_descriptor *out_desc;
+
+ /* REVISIT avoid this CDC-ACM support harder ... */
+ struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */
+};
+
+/* port setup/teardown is handled by gadget driver */
+int gserial_setup(struct usb_gadget *g, unsigned n_ports);
+void gserial_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+int gserial_connect(struct gserial *, u8 port_num);
+void gserial_disconnect(struct gserial *);
+
+/* functions are bound to configurations by a config or gadget driver */
+int acm_bind_config(struct usb_configuration *c, u8 port_num);
+int gser_bind_config(struct usb_configuration *c, u8 port_num);
+
+#endif /* __U_SERIAL_H */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index fce4924dbbe..aa0bd4f126a 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1,8 +1,8 @@
/*
* zero.c -- Gadget Zero, for USB development
*
- * Copyright (C) 2003-2007 David Brownell
- * All rights reserved.
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
*
* 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
@@ -30,12 +30,7 @@
*
* It supports two similar configurations. One sinks whatever the usb host
* writes, and in return sources zeroes. The other loops whatever the host
- * writes back, so the host can read it. Module options include:
- *
- * buflen=N default N=4096, buffer size used
- * qlen=N default N=32, how many buffers in the loopback queue
- * loopdefault default false, list loopback config first
- * autoresume=N default N=0, seconds before triggering remote wakeup
+ * writes back, so the host can read it.
*
* Many drivers will only have one configuration, letting them be much
* simpler if they also don't support high speed operation (like this
@@ -47,94 +42,35 @@
* work with low capability USB controllers without four bulk endpoints.
*/
+/*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
/* #define VERBOSE_DEBUG */
#include <linux/kernel.h>
#include <linux/utsname.h>
#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
+#include "g_zero.h"
#include "gadget_chips.h"
/*-------------------------------------------------------------------------*/
-#define DRIVER_VERSION "Earth Day 2008"
+#define DRIVER_VERSION "Cinco de Mayo 2008"
-static const char shortname[] = "zero";
static const char longname[] = "Gadget Zero";
-static const char source_sink[] = "source and sink data";
-static const char loopback[] = "loop input to output";
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * driver assumes self-powered hardware, and
- * has no way for users to trigger remote wakeup.
- *
- * this version autoconfigures as much as possible,
- * which is reasonable for most "bulk-only" drivers.
- */
-static const char *EP_IN_NAME; /* source */
-static const char *EP_OUT_NAME; /* sink */
-
-/*-------------------------------------------------------------------------*/
-
-/* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ 256
-
-struct zero_dev {
- spinlock_t lock;
- struct usb_gadget *gadget;
- struct usb_request *req; /* for control responses */
-
- /* when configured, we have one of two configs:
- * - source data (in to host) and sink it (out from host)
- * - or loop it back (out from host back in to host)
- */
- u8 config;
- struct usb_ep *in_ep, *out_ep;
-
- /* autoresume timer */
- struct timer_list resume;
-};
-
-#define DBG(d, fmt, args...) \
- dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
- dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
- dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
- dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
- dev_info(&(d)->gadget->dev , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static unsigned buflen = 4096;
-static unsigned qlen = 32;
-static unsigned pattern = 0;
-
-module_param(buflen, uint, S_IRUGO);
-module_param(qlen, uint, S_IRUGO);
-module_param(pattern, uint, S_IRUGO|S_IWUSR);
-
-/*
- * if it's nonzero, autoresume says how many seconds to wait
- * before trying to wake up the host after suspend.
- */
-static unsigned autoresume = 0;
-module_param(autoresume, uint, 0);
+unsigned buflen = 4096;
+module_param(buflen, uint, 0);
/*
* Normally the "loopback" configuration is second (index 1) so
* it's not the default. Here's where to change that order, to
- * work better with hosts where config changes are problematic.
- * Or controllers (like superh) that only support one config.
+ * work better with hosts where config changes are problematic or
+ * controllers (like original superh) that only support one config.
*/
static int loopdefault = 0;
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
@@ -156,24 +92,6 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
/*-------------------------------------------------------------------------*/
-/*
- * DESCRIPTORS ... most are static, but strings and (full)
- * configuration descriptors are built on demand.
- */
-
-#define STRING_MANUFACTURER 25
-#define STRING_PRODUCT 42
-#define STRING_SERIAL 101
-#define STRING_SOURCE_SINK 250
-#define STRING_LOOPBACK 251
-
-/*
- * This device advertises two configurations; these numbers work
- * on a pxa250 as well as more flexible hardware.
- */
-#define CONFIG_SOURCE_SINK 3
-#define CONFIG_LOOPBACK 2
-
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
@@ -183,248 +101,64 @@ static struct usb_device_descriptor device_desc = {
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
- .iManufacturer = STRING_MANUFACTURER,
- .iProduct = STRING_PRODUCT,
- .iSerialNumber = STRING_SERIAL,
.bNumConfigurations = 2,
};
-static struct usb_config_descriptor source_sink_config = {
- .bLength = sizeof source_sink_config,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* compute wTotalLength on the fly */
- .bNumInterfaces = 1,
- .bConfigurationValue = CONFIG_SOURCE_SINK,
- .iConfiguration = STRING_SOURCE_SINK,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* self-powered */
-};
-
-static struct usb_config_descriptor loopback_config = {
- .bLength = sizeof loopback_config,
- .bDescriptorType = USB_DT_CONFIG,
-
- /* compute wTotalLength on the fly */
- .bNumInterfaces = 1,
- .bConfigurationValue = CONFIG_LOOPBACK,
- .iConfiguration = STRING_LOOPBACK,
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
- .bMaxPower = 1, /* self-powered */
-};
-
+#ifdef CONFIG_USB_OTG
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-/* one interface in each configuration */
-
-static const struct usb_interface_descriptor source_sink_intf = {
- .bLength = sizeof source_sink_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .iInterface = STRING_SOURCE_SINK,
-};
-
-static const struct usb_interface_descriptor loopback_intf = {
- .bLength = sizeof loopback_intf,
- .bDescriptorType = USB_DT_INTERFACE,
-
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .iInterface = STRING_LOOPBACK,
-};
-
-/* two full speed bulk endpoints; their use is config-dependent */
-
-static struct usb_endpoint_descriptor fs_source_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor fs_sink_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bEndpointAddress = USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *fs_source_sink_function[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- (struct usb_descriptor_header *) &source_sink_intf,
- (struct usb_descriptor_header *) &fs_sink_desc,
- (struct usb_descriptor_header *) &fs_source_desc,
- NULL,
-};
-
-static const struct usb_descriptor_header *fs_loopback_function[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- (struct usb_descriptor_header *) &loopback_intf,
- (struct usb_descriptor_header *) &fs_sink_desc,
- (struct usb_descriptor_header *) &fs_source_desc,
- NULL,
-};
-
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- *
- * that means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the config descriptor.
- */
-
-static struct usb_endpoint_descriptor hs_source_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor hs_sink_desc = {
- .bLength = USB_DT_ENDPOINT_SIZE,
- .bDescriptorType = USB_DT_ENDPOINT,
-
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = __constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_VENDOR_SPEC,
-
- .bNumConfigurations = 2,
+ /* REVISIT SRP-only hardware is possible, although
+ * it would not be called "OTG" ...
+ */
+ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
-static const struct usb_descriptor_header *hs_source_sink_function[] = {
+const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
- (struct usb_descriptor_header *) &source_sink_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
NULL,
};
+#endif
-static const struct usb_descriptor_header *hs_loopback_function[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- (struct usb_descriptor_header *) &loopback_intf,
- (struct usb_descriptor_header *) &hs_source_desc,
- (struct usb_descriptor_header *) &hs_sink_desc,
- NULL,
-};
+/* string IDs are assigned dynamically */
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
- struct usb_endpoint_descriptor *fs)
-{
- if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
- return hs;
- return fs;
-}
+#define STRING_MANUFACTURER_IDX 0
+#define STRING_PRODUCT_IDX 1
+#define STRING_SERIAL_IDX 2
static char manufacturer[50];
/* default serial number takes at least two packets */
static char serial[] = "0123456789.0123456789.0123456789";
-
-/* static strings, in UTF-8 */
-static struct usb_string strings[] = {
- { STRING_MANUFACTURER, manufacturer, },
- { STRING_PRODUCT, longname, },
- { STRING_SERIAL, serial, },
- { STRING_LOOPBACK, loopback, },
- { STRING_SOURCE_SINK, source_sink, },
+static struct usb_string strings_dev[] = {
+ [STRING_MANUFACTURER_IDX].s = manufacturer,
+ [STRING_PRODUCT_IDX].s = longname,
+ [STRING_SERIAL_IDX].s = serial,
{ } /* end of list */
};
-static struct usb_gadget_strings stringtab = {
+static struct usb_gadget_strings stringtab_dev = {
.language = 0x0409, /* en-us */
- .strings = strings,
+ .strings = strings_dev,
};
-/*
- * config descriptors are also handcrafted. these must agree with code
- * that sets configurations, and with code managing interfaces and their
- * altsettings. other complexity may come from:
- *
- * - high speed support, including "other speed config" rules
- * - multiple configurations
- * - interfaces with alternate settings
- * - embedded class or vendor-specific descriptors
- *
- * this handles high speed, and has a second config that could as easily
- * have been an alternate interface setting (on most hardware).
- *
- * NOTE: to demonstrate (and test) more USB capabilities, this driver
- * should include an altsetting to test interrupt transfers, including
- * high bandwidth modes at high speed. (Maybe work like Intel's test
- * device?)
- */
-static int config_buf(struct usb_gadget *gadget,
- u8 *buf, u8 type, unsigned index)
-{
- int is_source_sink;
- int len;
- const struct usb_descriptor_header **function;
- int hs = 0;
-
- /* two configurations will always be index 0 and index 1 */
- if (index > 1)
- return -EINVAL;
- is_source_sink = loopdefault ? (index == 1) : (index == 0);
-
- if (gadget_is_dualspeed(gadget)) {
- hs = (gadget->speed == USB_SPEED_HIGH);
- if (type == USB_DT_OTHER_SPEED_CONFIG)
- hs = !hs;
- }
- if (hs)
- function = is_source_sink
- ? hs_source_sink_function
- : hs_loopback_function;
- else
- function = is_source_sink
- ? fs_source_sink_function
- : fs_loopback_function;
-
- /* for now, don't advertise srp-only devices */
- if (!gadget_is_otg(gadget))
- function++;
-
- len = usb_gadget_config_buf(is_source_sink
- ? &source_sink_config
- : &loopback_config,
- buf, USB_BUFSIZ, function);
- if (len < 0)
- return len;
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
- return len;
-}
+static struct usb_gadget_strings *dev_strings[] = {
+ &stringtab_dev,
+ NULL,
+};
/*-------------------------------------------------------------------------*/
-static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+struct usb_request *alloc_ep_req(struct usb_ep *ep)
{
struct usb_request *req;
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
- req->length = length;
- req->buf = kmalloc(length, GFP_ATOMIC);
+ req->length = buflen;
+ req->buf = kmalloc(buflen, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request(ep, req);
req = NULL;
@@ -433,681 +167,73 @@ static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
return req;
}
-static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request(ep, req);
}
-/*-------------------------------------------------------------------------*/
-
-/*
- * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals,
- * this just sinks bulk packets OUT to the peripheral and sources them IN
- * to the host, optionally with specific data patterns.
- *
- * In terms of control messaging, this supports all the standard requests
- * plus two that support control-OUT tests.
- *
- * Note that because this doesn't queue more than one request at a time,
- * some other function must be used to test queueing logic. The network
- * link (g_ether) is probably the best option for that.
- */
-
-/* optionally require specific source/sink data patterns */
-
-static int
-check_read_data(
- struct zero_dev *dev,
- struct usb_ep *ep,
- struct usb_request *req
-)
+static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
{
- unsigned i;
- u8 *buf = req->buf;
-
- for (i = 0; i < req->actual; i++, buf++) {
- switch (pattern) {
- /* all-zeroes has no synchronization issues */
- case 0:
- if (*buf == 0)
- continue;
- break;
- /* mod63 stays in sync with short-terminated transfers,
- * or otherwise when host and gadget agree on how large
- * each usb transfer request should be. resync is done
- * with set_interface or set_config.
- */
- case 1:
- if (*buf == (u8)(i % 63))
- continue;
- break;
- }
- ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
- usb_ep_set_halt(ep);
- return -EINVAL;
+ int value;
+
+ if (ep->driver_data) {
+ value = usb_ep_disable(ep);
+ if (value < 0)
+ DBG(cdev, "disable %s --> %d\n",
+ ep->name, value);
+ ep->driver_data = NULL;
}
- return 0;
}
-static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+void disable_endpoints(struct usb_composite_dev *cdev,
+ struct usb_ep *in, struct usb_ep *out)
{
- unsigned i;
- u8 *buf = req->buf;
-
- switch (pattern) {
- case 0:
- memset(req->buf, 0, req->length);
- break;
- case 1:
- for (i = 0; i < req->length; i++)
- *buf++ = (u8) (i % 63);
- break;
- }
-}
-
-/* if there is only one request in the queue, there'll always be an
- * irq delay between end of one request and start of the next.
- * that prevents using hardware dma queues.
- */
-static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct zero_dev *dev = ep->driver_data;
- int status = req->status;
-
- switch (status) {
-
- case 0: /* normal completion? */
- if (ep == dev->out_ep) {
- check_read_data(dev, ep, req);
- memset(req->buf, 0x55, req->length);
- } else
- reinit_write_data(ep, req);
- break;
-
- /* this endpoint is normally active while we're configured */
- case -ECONNABORTED: /* hardware forced ep reset */
- case -ECONNRESET: /* request dequeued */
- case -ESHUTDOWN: /* disconnect from host */
- VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
- req->actual, req->length);
- if (ep == dev->out_ep)
- check_read_data(dev, ep, req);
- free_ep_req(ep, req);
- return;
-
- case -EOVERFLOW: /* buffer overrun on read means that
- * we didn't provide a big enough
- * buffer.
- */
- default:
-#if 1
- DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
- status, req->actual, req->length);
-#endif
- case -EREMOTEIO: /* short read */
- break;
- }
-
- status = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (status) {
- ERROR(dev, "kill %s: resubmit %d bytes --> %d\n",
- ep->name, req->length, status);
- usb_ep_set_halt(ep);
- /* FIXME recover later ... somehow */
- }
-}
-
-static struct usb_request *source_sink_start_ep(struct usb_ep *ep)
-{
- struct usb_request *req;
- int status;
-
- req = alloc_ep_req(ep, buflen);
- if (!req)
- return NULL;
-
- memset(req->buf, 0, req->length);
- req->complete = source_sink_complete;
-
- if (strcmp(ep->name, EP_IN_NAME) == 0)
- reinit_write_data(ep, req);
- else
- memset(req->buf, 0x55, req->length);
-
- status = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (status) {
- struct zero_dev *dev = ep->driver_data;
-
- ERROR(dev, "start %s --> %d\n", ep->name, status);
- free_ep_req(ep, req);
- req = NULL;
- }
-
- return req;
-}
-
-static int set_source_sink_config(struct zero_dev *dev)
-{
- int result = 0;
- struct usb_ep *ep;
- struct usb_gadget *gadget = dev->gadget;
-
- gadget_for_each_ep(ep, gadget) {
- const struct usb_endpoint_descriptor *d;
-
- /* one endpoint writes (sources) zeroes in (to the host) */
- if (strcmp(ep->name, EP_IN_NAME) == 0) {
- d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
- result = usb_ep_enable(ep, d);
- if (result == 0) {
- ep->driver_data = dev;
- if (source_sink_start_ep(ep) != NULL) {
- dev->in_ep = ep;
- continue;
- }
- usb_ep_disable(ep);
- result = -EIO;
- }
-
- /* one endpoint reads (sinks) anything out (from the host) */
- } else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
- d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
- result = usb_ep_enable(ep, d);
- if (result == 0) {
- ep->driver_data = dev;
- if (source_sink_start_ep(ep) != NULL) {
- dev->out_ep = ep;
- continue;
- }
- usb_ep_disable(ep);
- result = -EIO;
- }
-
- /* ignore any other endpoints */
- } else
- continue;
-
- /* stop on error */
- ERROR(dev, "can't start %s, result %d\n", ep->name, result);
- break;
- }
- if (result == 0)
- DBG(dev, "buflen %d\n", buflen);
-
- /* caller is responsible for cleanup on error */
- return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct zero_dev *dev = ep->driver_data;
- int status = req->status;
-
- switch (status) {
-
- case 0: /* normal completion? */
- if (ep == dev->out_ep) {
- /* loop this OUT packet back IN to the host */
- req->zero = (req->actual < req->length);
- req->length = req->actual;
- status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
- if (status == 0)
- return;
-
- /* "should never get here" */
- ERROR(dev, "can't loop %s to %s: %d\n",
- ep->name, dev->in_ep->name,
- status);
- }
-
- /* queue the buffer for some later OUT packet */
- req->length = buflen;
- status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
- if (status == 0)
- return;
-
- /* "should never get here" */
- /* FALLTHROUGH */
-
- default:
- ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name,
- status, req->actual, req->length);
- /* FALLTHROUGH */
-
- /* NOTE: since this driver doesn't maintain an explicit record
- * of requests it submitted (just maintains qlen count), we
- * rely on the hardware driver to clean up on disconnect or
- * endpoint disable.
- */
- case -ECONNABORTED: /* hardware forced ep reset */
- case -ECONNRESET: /* request dequeued */
- case -ESHUTDOWN: /* disconnect from host */
- free_ep_req(ep, req);
- return;
- }
-}
-
-static int set_loopback_config(struct zero_dev *dev)
-{
- int result = 0;
- struct usb_ep *ep;
- struct usb_gadget *gadget = dev->gadget;
-
- gadget_for_each_ep(ep, gadget) {
- const struct usb_endpoint_descriptor *d;
-
- /* one endpoint writes data back IN to the host */
- if (strcmp(ep->name, EP_IN_NAME) == 0) {
- d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
- result = usb_ep_enable(ep, d);
- if (result == 0) {
- ep->driver_data = dev;
- dev->in_ep = ep;
- continue;
- }
-
- /* one endpoint just reads OUT packets */
- } else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
- d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
- result = usb_ep_enable(ep, d);
- if (result == 0) {
- ep->driver_data = dev;
- dev->out_ep = ep;
- continue;
- }
-
- /* ignore any other endpoints */
- } else
- continue;
-
- /* stop on error */
- ERROR(dev, "can't enable %s, result %d\n", ep->name, result);
- break;
- }
-
- /* allocate a bunch of read buffers and queue them all at once.
- * we buffer at most 'qlen' transfers; fewer if any need more
- * than 'buflen' bytes each.
- */
- if (result == 0) {
- struct usb_request *req;
- unsigned i;
-
- ep = dev->out_ep;
- for (i = 0; i < qlen && result == 0; i++) {
- req = alloc_ep_req(ep, buflen);
- if (req) {
- req->complete = loopback_complete;
- result = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (result)
- DBG(dev, "%s queue req --> %d\n",
- ep->name, result);
- } else
- result = -ENOMEM;
- }
- }
- if (result == 0)
- DBG(dev, "qlen %d, buflen %d\n", qlen, buflen);
-
- /* caller is responsible for cleanup on error */
- return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_reset_config(struct zero_dev *dev)
-{
- if (dev->config == 0)
- return;
-
- DBG(dev, "reset config\n");
-
- /* just disable endpoints, forcing completion of pending i/o.
- * all our completion handlers free their requests in this case.
- */
- if (dev->in_ep) {
- usb_ep_disable(dev->in_ep);
- dev->in_ep = NULL;
- }
- if (dev->out_ep) {
- usb_ep_disable(dev->out_ep);
- dev->out_ep = NULL;
- }
- dev->config = 0;
- del_timer(&dev->resume);
-}
-
-/* change our operational config. this code must agree with the code
- * that returns config descriptors, and altsetting code.
- *
- * it's also responsible for power management interactions. some
- * configurations might not work with our current power sources.
- *
- * note that some device controller hardware will constrain what this
- * code can do, perhaps by disallowing more than one configuration or
- * by limiting configuration choices (like the pxa2xx).
- */
-static int zero_set_config(struct zero_dev *dev, unsigned number)
-{
- int result = 0;
- struct usb_gadget *gadget = dev->gadget;
-
- if (number == dev->config)
- return 0;
-
- if (gadget_is_sa1100(gadget) && dev->config) {
- /* tx fifo is full, but we can't clear it...*/
- ERROR(dev, "can't change configurations\n");
- return -ESPIPE;
- }
- zero_reset_config(dev);
-
- switch (number) {
- case CONFIG_SOURCE_SINK:
- result = set_source_sink_config(dev);
- break;
- case CONFIG_LOOPBACK:
- result = set_loopback_config(dev);
- break;
- default:
- result = -EINVAL;
- /* FALL THROUGH */
- case 0:
- return result;
- }
-
- if (!result && (!dev->in_ep || !dev->out_ep))
- result = -ENODEV;
- if (result)
- zero_reset_config(dev);
- else {
- char *speed;
-
- switch (gadget->speed) {
- case USB_SPEED_LOW: speed = "low"; break;
- case USB_SPEED_FULL: speed = "full"; break;
- case USB_SPEED_HIGH: speed = "high"; break;
- default: speed = "?"; break;
- }
-
- dev->config = number;
- INFO(dev, "%s speed config #%d: %s\n", speed, number,
- (number == CONFIG_SOURCE_SINK)
- ? source_sink : loopback);
- }
- return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
- if (req->status || req->actual != req->length)
- DBG((struct zero_dev *) ep->driver_data,
- "setup complete --> %d, %d/%d\n",
- req->status, req->actual, req->length);
-}
-
-/*
- * The setup() callback implements all the ep0 functionality that's
- * not handled lower down, in hardware or the hardware driver (like
- * device and endpoint feature flags, and their status). It's all
- * housekeeping for the gadget function we're implementing. Most of
- * the work is in config-specific setup.
- */
-static int
-zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
- struct zero_dev *dev = get_gadget_data(gadget);
- struct usb_request *req = dev->req;
- int value = -EOPNOTSUPP;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
-
- /* usually this stores reply data in the pre-allocated ep0 buffer,
- * but config change events will reconfigure hardware.
- */
- req->zero = 0;
- switch (ctrl->bRequest) {
-
- case USB_REQ_GET_DESCRIPTOR:
- if (ctrl->bRequestType != USB_DIR_IN)
- goto unknown;
- switch (w_value >> 8) {
-
- case USB_DT_DEVICE:
- value = min(w_length, (u16) sizeof device_desc);
- memcpy(req->buf, &device_desc, value);
- break;
- case USB_DT_DEVICE_QUALIFIER:
- if (!gadget_is_dualspeed(gadget))
- break;
- value = min(w_length, (u16) sizeof dev_qualifier);
- memcpy(req->buf, &dev_qualifier, value);
- break;
-
- case USB_DT_OTHER_SPEED_CONFIG:
- if (!gadget_is_dualspeed(gadget))
- break;
- // FALLTHROUGH
- case USB_DT_CONFIG:
- value = config_buf(gadget, req->buf,
- w_value >> 8,
- w_value & 0xff);
- if (value >= 0)
- value = min(w_length, (u16) value);
- break;
-
- case USB_DT_STRING:
- /* wIndex == language code.
- * this driver only handles one language, you can
- * add string tables for other languages, using
- * any UTF-8 characters
- */
- value = usb_gadget_get_string(&stringtab,
- w_value & 0xff, req->buf);
- if (value >= 0)
- value = min(w_length, (u16) value);
- break;
- }
- break;
-
- /* currently two configs, two speeds */
- case USB_REQ_SET_CONFIGURATION:
- if (ctrl->bRequestType != 0)
- goto unknown;
- if (gadget->a_hnp_support)
- DBG(dev, "HNP available\n");
- else if (gadget->a_alt_hnp_support)
- DBG(dev, "HNP needs a different root port\n");
- else
- VDBG(dev, "HNP inactive\n");
- spin_lock(&dev->lock);
- value = zero_set_config(dev, w_value);
- spin_unlock(&dev->lock);
- break;
- case USB_REQ_GET_CONFIGURATION:
- if (ctrl->bRequestType != USB_DIR_IN)
- goto unknown;
- *(u8 *)req->buf = dev->config;
- value = min(w_length, (u16) 1);
- break;
-
- /* until we add altsetting support, or other interfaces,
- * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
- * and already killed pending endpoint I/O.
- */
- case USB_REQ_SET_INTERFACE:
- if (ctrl->bRequestType != USB_RECIP_INTERFACE)
- goto unknown;
- spin_lock(&dev->lock);
- if (dev->config && w_index == 0 && w_value == 0) {
- u8 config = dev->config;
-
- /* resets interface configuration, forgets about
- * previous transaction state (queued bufs, etc)
- * and re-inits endpoint state (toggle etc)
- * no response queued, just zero status == success.
- * if we had more than one interface we couldn't
- * use this "reset the config" shortcut.
- */
- zero_reset_config(dev);
- zero_set_config(dev, config);
- value = 0;
- }
- spin_unlock(&dev->lock);
- break;
- case USB_REQ_GET_INTERFACE:
- if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
- goto unknown;
- if (!dev->config)
- break;
- if (w_index != 0) {
- value = -EDOM;
- break;
- }
- *(u8 *)req->buf = 0;
- value = min(w_length, (u16) 1);
- break;
-
- /*
- * These are the same vendor-specific requests supported by
- * Intel's USB 2.0 compliance test devices. We exceed that
- * device spec by allowing multiple-packet requests.
- */
- case 0x5b: /* control WRITE test -- fill the buffer */
- if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
- goto unknown;
- if (w_value || w_index)
- break;
- /* just read that many bytes into the buffer */
- if (w_length > USB_BUFSIZ)
- break;
- value = w_length;
- break;
- case 0x5c: /* control READ test -- return the buffer */
- if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
- goto unknown;
- if (w_value || w_index)
- break;
- /* expect those bytes are still in the buffer; send back */
- if (w_length > USB_BUFSIZ
- || w_length != req->length)
- break;
- value = w_length;
- break;
-
- default:
-unknown:
- VDBG(dev,
- "unknown control req%02x.%02x v%04x i%04x l%d\n",
- ctrl->bRequestType, ctrl->bRequest,
- w_value, w_index, w_length);
- }
-
- /* respond with data transfer before status phase? */
- if (value >= 0) {
- req->length = value;
- req->zero = value < w_length;
- value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
- if (value < 0) {
- DBG(dev, "ep_queue --> %d\n", value);
- req->status = 0;
- zero_setup_complete(gadget->ep0, req);
- }
- }
-
- /* device either stalls (value < 0) or reports success */
- return value;
-}
-
-static void zero_disconnect(struct usb_gadget *gadget)
-{
- struct zero_dev *dev = get_gadget_data(gadget);
- unsigned long flags;
-
- spin_lock_irqsave(&dev->lock, flags);
- zero_reset_config(dev);
-
- /* a more significant application might have some non-usb
- * activities to quiesce here, saving resources like power
- * or pushing the notification up a network stack.
- */
- spin_unlock_irqrestore(&dev->lock, flags);
-
- /* next we may get setup() calls to enumerate new connections;
- * or an unbind() during shutdown (including removing module).
- */
-}
-
-static void zero_autoresume(unsigned long _dev)
-{
- struct zero_dev *dev = (struct zero_dev *) _dev;
- int status;
-
- /* normally the host would be woken up for something
- * more significant than just a timer firing...
- */
- if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
- status = usb_gadget_wakeup(dev->gadget);
- DBG(dev, "wakeup --> %d\n", status);
- }
+ disable_ep(cdev, in);
+ disable_ep(cdev, out);
}
/*-------------------------------------------------------------------------*/
-static void zero_unbind(struct usb_gadget *gadget)
+static int __init zero_bind(struct usb_composite_dev *cdev)
{
- struct zero_dev *dev = get_gadget_data(gadget);
-
- DBG(dev, "unbind\n");
-
- /* we've already been disconnected ... no i/o is active */
- if (dev->req) {
- dev->req->length = USB_BUFSIZ;
- free_ep_req(gadget->ep0, dev->req);
- }
- del_timer_sync(&dev->resume);
- kfree(dev);
- set_gadget_data(gadget, NULL);
-}
-
-static int __init zero_bind(struct usb_gadget *gadget)
-{
- struct zero_dev *dev;
- struct usb_ep *ep;
int gcnum;
+ struct usb_gadget *gadget = cdev->gadget;
+ int id;
- /* FIXME this can't yet work right with SH ... it has only
- * one configuration, numbered one.
+ /* Allocate string descriptor numbers ... note that string
+ * contents can be overridden by the composite_dev glue.
*/
- if (gadget_is_sh(gadget))
- return -ENODEV;
-
- /* Bulk-only drivers like this one SHOULD be able to
- * autoconfigure on any sane usb controller driver,
- * but there may also be important quirks to address.
+ id = usb_string_id(cdev);
+ if (id < 0)
+ return id;
+ strings_dev[STRING_MANUFACTURER_IDX].id = id;
+ device_desc.iManufacturer = id;
+
+ id = usb_string_id(cdev);
+ if (id < 0)
+ return id;
+ strings_dev[STRING_PRODUCT_IDX].id = id;
+ device_desc.iProduct = id;
+
+ id = usb_string_id(cdev);
+ if (id < 0)
+ return id;
+ strings_dev[STRING_SERIAL_IDX].id = id;
+ device_desc.iSerialNumber = id;
+
+ /* Register primary, then secondary configuration. Note that
+ * SH3 only allows one config...
*/
- usb_ep_autoconfig_reset(gadget);
- ep = usb_ep_autoconfig(gadget, &fs_source_desc);
- if (!ep) {
-autoconf_fail:
- pr_err("%s: can't autoconfigure on %s\n",
- shortname, gadget->name);
- return -ENODEV;
+ if (loopdefault) {
+ loopback_add(cdev);
+ if (!gadget_is_sh(gadget))
+ sourcesink_add(cdev);
+ } else {
+ sourcesink_add(cdev);
+ if (!gadget_is_sh(gadget))
+ loopback_add(cdev);
}
- EP_IN_NAME = ep->name;
- ep->driver_data = ep; /* claim */
-
- ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
- if (!ep)
- goto autoconf_fail;
- EP_OUT_NAME = ep->name;
- ep->driver_data = ep; /* claim */
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
@@ -1115,144 +241,44 @@ autoconf_fail:
else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
- * so warn about unrcognized controllers, don't panic.
+ * so just warn about unrcognized controllers -- don't panic.
*
* things like configuration and altsetting numbering
* can need hardware-specific attention though.
*/
pr_warning("%s: controller '%s' not recognized\n",
- shortname, gadget->name);
+ longname, gadget->name);
device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
}
- /* ok, we made sense of the hardware ... */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
- spin_lock_init(&dev->lock);
- dev->gadget = gadget;
- set_gadget_data(gadget, dev);
-
- init_timer(&dev->resume);
- dev->resume.function = zero_autoresume;
- dev->resume.data = (unsigned long) dev;
-
- /* preallocate control response and buffer */
- dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
- if (!dev->req)
- goto enomem;
- dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
- if (!dev->req->buf)
- goto enomem;
-
- dev->req->complete = zero_setup_complete;
-
- device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
- if (gadget_is_dualspeed(gadget)) {
- /* assume ep0 uses the same value for both speeds ... */
- dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
- /* and that all endpoints are dual-speed */
- hs_source_desc.bEndpointAddress =
- fs_source_desc.bEndpointAddress;
- hs_sink_desc.bEndpointAddress =
- fs_sink_desc.bEndpointAddress;
- }
-
- if (gadget_is_otg(gadget)) {
- otg_descriptor.bmAttributes |= USB_OTG_HNP,
- source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- }
-
- usb_gadget_set_selfpowered(gadget);
-
- if (autoresume) {
- source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
- }
-
- gadget->ep0->driver_data = dev;
-
- INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
- INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
- EP_OUT_NAME, EP_IN_NAME);
+ INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
return 0;
-
-enomem:
- zero_unbind(gadget);
- return -ENOMEM;
}
-/*-------------------------------------------------------------------------*/
-
-static void zero_suspend(struct usb_gadget *gadget)
-{
- struct zero_dev *dev = get_gadget_data(gadget);
-
- if (gadget->speed == USB_SPEED_UNKNOWN)
- return;
-
- if (autoresume) {
- mod_timer(&dev->resume, jiffies + (HZ * autoresume));
- DBG(dev, "suspend, wakeup in %d seconds\n", autoresume);
- } else
- DBG(dev, "suspend\n");
-}
-
-static void zero_resume(struct usb_gadget *gadget)
-{
- struct zero_dev *dev = get_gadget_data(gadget);
-
- DBG(dev, "resume\n");
- del_timer(&dev->resume);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver zero_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
- .speed = USB_SPEED_HIGH,
-#else
- .speed = USB_SPEED_FULL,
-#endif
- .function = (char *) longname,
+static struct usb_composite_driver zero_driver = {
+ .name = "zero",
+ .dev = &device_desc,
+ .strings = dev_strings,
.bind = zero_bind,
- .unbind = __exit_p(zero_unbind),
-
- .setup = zero_setup,
- .disconnect = zero_disconnect,
-
- .suspend = zero_suspend,
- .resume = zero_resume,
-
- .driver = {
- .name = (char *) shortname,
- .owner = THIS_MODULE,
- },
};
MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
-
static int __init init(void)
{
- return usb_gadget_register_driver(&zero_driver);
+ return usb_composite_register(&zero_driver);
}
module_init(init);
static void __exit cleanup(void)
{
- usb_gadget_unregister_driver(&zero_driver);
+ usb_composite_unregister(&zero_driver);
}
module_exit(cleanup);
-
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 08a4335401a..bf69f473910 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -19,263 +19,304 @@
#define USB_MCFG_RDCOMB (1<<30)
#define USB_MCFG_SSDEN (1<<23)
#define USB_MCFG_PHYPLLEN (1<<19)
+#define USB_MCFG_UCECLKEN (1<<18)
#define USB_MCFG_EHCCLKEN (1<<17)
+#ifdef CONFIG_DMA_COHERENT
#define USB_MCFG_UCAM (1<<7)
+#else
+#define USB_MCFG_UCAM (0)
+#endif
#define USB_MCFG_EBMEN (1<<3)
#define USB_MCFG_EMEMEN (1<<2)
-#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN)
+#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN)
+#define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \
+ USBH_ENABLE_CE | USB_MCFG_SSDEN | \
+ USB_MCFG_UCAM | USB_MCFG_EBMEN | \
+ USB_MCFG_EMEMEN)
-#ifdef CONFIG_DMA_COHERENT
-#define USBH_ENABLE_INIT (USBH_ENABLE_CE \
- | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
- | USB_MCFG_SSDEN | USB_MCFG_UCAM \
- | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
-#else
-#define USBH_ENABLE_INIT (USBH_ENABLE_CE \
- | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
- | USB_MCFG_SSDEN \
- | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
-#endif
#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
extern int usb_disabled(void);
-/*-------------------------------------------------------------------------*/
-
-static void au1xxx_start_ehc(struct platform_device *dev)
+static void au1xxx_start_ehc(void)
{
- pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n");
-
- /* write HW defaults again in case Yamon cleared them */
- if (au_readl(USB_HOST_CONFIG) == 0) {
- au_writel(0x00d02000, USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
- udelay(1000);
- }
- /* enable host controller */
- au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
- udelay(1000);
- au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG),
- USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
+ /* enable clock to EHCI block and HS PHY PLL*/
+ au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG);
+ au_sync();
udelay(1000);
- pr_debug(__FILE__ ": Clock to USB host has been enabled\n");
+ /* enable EHCI mmio */
+ au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+ au_sync();
+ udelay(1000);
}
-static void au1xxx_stop_ehc(struct platform_device *dev)
+static void au1xxx_stop_ehc(void)
{
- pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n");
+ unsigned long c;
/* Disable mem */
- au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
+ au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG);
+ au_sync();
udelay(1000);
- /* Disable clock */
- au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG),
- USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
+
+ /* Disable EHC clock. If the HS PHY is unused disable it too. */
+ c = au_readl(USB_HOST_CONFIG) & ~USB_MCFG_EHCCLKEN;
+ if (!(c & USB_MCFG_UCECLKEN)) /* UDC disabled? */
+ c &= ~USB_MCFG_PHYPLLEN; /* yes: disable HS PHY PLL */
+ au_writel(c, USB_HOST_CONFIG);
+ au_sync();
}
-/*-------------------------------------------------------------------------*/
+static const struct hc_driver ehci_au1xxx_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "Au1xxx EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ *
+ * FIXME -- ehci_init() doesn't do enough here.
+ * See ehci-ppc-soc for a complete implementation.
+ */
+ .reset = ehci_init,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
-/**
- * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_ehci_au1xxx_probe(const struct hc_driver *driver,
- struct usb_hcd **hcd_out, struct platform_device *dev)
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+};
+
+static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
{
- int retval;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
+ int ret;
-#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
+ if (usb_disabled())
+ return -ENODEV;
+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
/* Au1200 AB USB does not support coherent memory */
if (!(read_c0_prid() & 0xff)) {
- pr_info("%s: this is chip revision AB!\n", dev->name);
- pr_info("%s: update your board or re-configure the kernel\n",
- dev->name);
+ printk(KERN_INFO "%s: this is chip revision AB!\n", pdev->name);
+ printk(KERN_INFO "%s: update your board or re-configure"
+ " the kernel\n", pdev->name);
return -ENODEV;
}
#endif
- au1xxx_start_ehc(dev);
-
- if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
pr_debug("resource[1] is not IORESOURCE_IRQ");
- retval = -ENOMEM;
+ return -ENOMEM;
}
- hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx");
+ hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
if (!hcd)
return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+ hcd->rsrc_start = pdev->resource[0].start;
+ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed");
- retval = -EBUSY;
+ ret = -EBUSY;
goto err1;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed");
- retval = -ENOMEM;
+ ret = -ENOMEM;
goto err2;
}
+ au1xxx_start_ehc();
+
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = readl(&ehci->caps->hcs_params);
- /* ehci_hcd_init(hcd_to_ehci(hcd)); */
-
- retval =
- usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED);
- if (retval == 0)
- return retval;
+ ret = usb_add_hcd(hcd, pdev->resource[1].start,
+ IRQF_DISABLED | IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
+ return ret;
+ }
- au1xxx_stop_ehc(dev);
+ au1xxx_stop_ehc();
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
usb_put_hcd(hcd);
- return retval;
+ return ret;
}
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev)
+static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
usb_remove_hcd(hcd);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- au1xxx_stop_ehc(dev);
+ au1xxx_stop_ehc();
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
}
-/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_PM
+static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
+ pm_message_t message)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ unsigned long flags;
+ int rc;
-static const struct hc_driver ehci_au1xxx_hc_driver = {
- .description = hcd_name,
- .product_desc = "Au1xxx EHCI",
- .hcd_priv_size = sizeof(struct ehci_hcd),
+ return 0;
+ rc = 0;
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(10);
- /*
- * basic lifecycle operations
+ /* Root hub was already suspended. Disable irq emission and
+ * mark HW unaccessible, bail out if RH has been resumed. Use
+ * the spinlock to properly synchronize with possible pending
+ * RH suspend or resume activity.
*
- * FIXME -- ehci_init() doesn't do enough here.
- * See ehci-ppc-soc for a complete implementation.
- */
- .reset = ehci_init,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
+ * This is still racy as hcd->state is manipulated outside of
+ * any locks =P But that will be a different fix.
*/
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
+ spin_lock_irqsave(&ehci->lock, flags);
+ if (hcd->state != HC_STATE_SUSPENDED) {
+ rc = -EINVAL;
+ goto bail;
+ }
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ (void)ehci_readl(ehci, &ehci->regs->intr_enable);
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
+ /* make sure snapshot being resumed re-enumerates everything */
+ if (message.event == PM_EVENT_PRETHAW) {
+ ehci_halt(ehci);
+ ehci_reset(ehci);
+ }
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-};
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-/*-------------------------------------------------------------------------*/
+ au1xxx_stop_ehc();
-static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = NULL;
- int ret;
+bail:
+ spin_unlock_irqrestore(&ehci->lock, flags);
- pr_debug("In ehci_hcd_au1xxx_drv_probe\n");
+ // could save FLADJ in case of Vaux power loss
+ // ... we'd only use it to handle clock skew
- if (usb_disabled())
- return -ENODEV;
-
- /* FIXME we only want one one probe() not two */
- ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
- return ret;
+ return rc;
}
-static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
+
+static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- /* FIXME we only want one one remove() not two */
- usb_ehci_au1xxx_remove(hcd, pdev);
- return 0;
-}
+ au1xxx_start_ehc();
- /*TBD*/
-/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ // maybe restore FLADJ
- return 0;
-}
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(100);
+
+ /* Mark hardware accessible again as we are out of D3 state by now */
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ /* If CF is still set, we maintained PCI Vaux power.
+ * Just undo the effect of ehci_pci_suspend().
+ */
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+ return 0;
+ }
+
+ ehci_dbg(ehci, "lost power, restarting\n");
+ usb_root_hub_lost_power(hcd->self.root_hub);
+
+ /* Else reset, to cope with power loss or flush-to-storage
+ * style "resume" having let BIOS kick in during reboot.
+ */
+ (void) ehci_halt(ehci);
+ (void) ehci_reset(ehci);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq(&ehci->lock);
+ if (ehci->reclaim)
+ end_unlink_async(ehci);
+ ehci_work(ehci);
+ spin_unlock_irq(&ehci->lock);
+
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+
+ hcd->state = HC_STATE_SUSPENDED;
return 0;
}
-*/
-MODULE_ALIAS("platform:au1xxx-ehci");
+
+#else
+#define ehci_hcd_au1xxx_drv_suspend NULL
+#define ehci_hcd_au1xxx_drv_resume NULL
+#endif
+
static struct platform_driver ehci_hcd_au1xxx_driver = {
- .probe = ehci_hcd_au1xxx_drv_probe,
- .remove = ehci_hcd_au1xxx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
- /*.suspend = ehci_hcd_au1xxx_drv_suspend, */
- /*.resume = ehci_hcd_au1xxx_drv_resume, */
+ .probe = ehci_hcd_au1xxx_drv_probe,
+ .remove = ehci_hcd_au1xxx_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .suspend = ehci_hcd_au1xxx_drv_suspend,
+ .resume = ehci_hcd_au1xxx_drv_resume,
.driver = {
- .name = "au1xxx-ehci",
+ .name = "au1xxx-ehci",
+ .owner = THIS_MODULE,
}
};
+
+MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 0f82fdcaef0..b0f8ed5a7fb 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -676,7 +676,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
"%s\n"
"SUSPENDED (no register access)\n",
hcd->self.controller->bus->name,
- hcd->self.controller->bus_id,
+ dev_name(hcd->self.controller),
hcd->product_desc);
goto done;
}
@@ -688,7 +688,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
"%s\n"
"EHCI %x.%02x, hcd state %d\n",
hcd->self.controller->bus->name,
- hcd->self.controller->bus_id,
+ dev_name(hcd->self.controller),
hcd->product_desc,
i >> 8, i & 0x0ff, hcd->state);
size -= temp;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 7370d6187c6..01c3da34f67 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -56,7 +56,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev,
- "No platform data for %s.\n", pdev->dev.bus_id);
+ "No platform data for %s.\n", dev_name(&pdev->dev));
return -ENODEV;
}
@@ -69,7 +69,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
(pdata->operating_mode == FSL_USB2_DR_OTG))) {
dev_err(&pdev->dev,
"Non Host Mode configured for %s. Wrong driver linked.\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
return -ENODEV;
}
@@ -77,12 +77,12 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (!res) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
return -ENODEV;
}
irq = res->start;
- hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
goto err1;
@@ -92,7 +92,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (!res) {
dev_err(&pdev->dev,
"Found HC with no register addr. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
retval = -ENODEV;
goto err2;
}
@@ -132,7 +132,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
err2:
usb_put_hcd(hcd);
err1:
- dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+ dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
return retval;
}
@@ -230,8 +230,13 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
/* put controller in host mode. */
ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+#ifdef CONFIG_PPC_85xx
+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+#else
out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+#endif
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 369a8a5ea7b..d9d53f289ca 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -84,7 +84,7 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
-#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */
+#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
/* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index 9d042f22009..f9575c40912 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -77,12 +77,12 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
return -ENODEV;
}
irq = res->start;
- hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
goto fail_create_hcd;
@@ -92,7 +92,7 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev,
"Found HC with no register addr. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
retval = -ENODEV;
goto fail_request_resource;
}
@@ -126,7 +126,7 @@ fail_ioremap:
fail_request_resource:
usb_put_hcd(hcd);
fail_create_hcd:
- dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+ dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
return retval;
}
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index ab625f0ba1d..5fbdc14e63b 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -204,7 +204,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
if (irq <= 0) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
err = -ENODEV;
goto err1;
}
@@ -213,7 +213,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev,
"Found HC with no register addr. Check %s setup!\n",
- pdev->dev.bus_id);
+ dev_name(&pdev->dev));
err = -ENODEV;
goto err1;
}
@@ -233,7 +233,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
}
hcd = usb_create_hcd(&ehci_orion_hc_driver,
- &pdev->dev, pdev->dev.bus_id);
+ &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
err = -ENOMEM;
goto err3;
@@ -276,7 +276,7 @@ err2:
release_mem_region(res->start, res->end - res->start + 1);
err1:
dev_err(&pdev->dev, "init %s fail, %d\n",
- pdev->dev.bus_id, err);
+ dev_name(&pdev->dev), err);
return err;
}
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 37e6abeb794..0eba894bcb0 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -128,7 +128,7 @@ static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
- hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
+ hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev_name(&dev->core));
if (!hcd) {
dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b85b54160cd..2622b6596d7 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1116,8 +1116,7 @@ static void scan_async (struct ehci_hcd *ehci)
struct ehci_qh *qh;
enum ehci_timer_action action = TIMER_IO_WATCHDOG;
- if (!++(ehci->stamp))
- ehci->stamp++;
+ ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
timer_action_done (ehci, TIMER_ASYNC_SHRINK);
rescan:
qh = ehci->async->qh_next.qh;
@@ -1142,18 +1141,20 @@ rescan:
}
}
- /* unlink idle entries, reducing HC PCI usage as well
+ /* unlink idle entries, reducing DMA usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
*/
- if (list_empty (&qh->qtd_list)) {
- if (qh->stamp == ehci->stamp)
+ if (list_empty(&qh->qtd_list)
+ && qh->qh_state == QH_STATE_LINKED) {
+ if (!ehci->reclaim
+ && ((ehci->stamp - qh->stamp) & 0x1fff)
+ >= (EHCI_SHRINK_FRAMES * 8))
+ start_unlink_async(ehci, qh);
+ else
action = TIMER_ASYNC_SHRINK;
- else if (!ehci->reclaim
- && qh->qh_state == QH_STATE_LINKED)
- start_unlink_async (ehci, qh);
}
qh = qh->qh_next.qh;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 90245fd8bac..5799298364f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -198,7 +198,10 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
break;
// case TIMER_ASYNC_SHRINK:
default:
- t = EHCI_SHRINK_JIFFIES;
+ /* add a jiffie since we synch against the
+ * 8 KHz uframe counter.
+ */
+ t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
mod_timer(&ehci->watchdog, t + jiffies);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 20b9a0d0742..31178e10cbb 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -94,6 +94,10 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
u16 w;
int quot = len % 4;
+ /* buffer is already in 'usb data order', which is LE. */
+ /* When reading buffer as u16, we have to take care byte order */
+ /* doesn't get mixed up */
+
if ((unsigned long)dp2 & 1) {
/* not aligned */
for (; len > 1; len -= 2) {
@@ -105,8 +109,11 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
isp116x_write_data16(isp116x, (u16) * dp);
} else {
/* aligned */
- for (; len > 1; len -= 2)
- isp116x_raw_write_data16(isp116x, *dp2++);
+ for (; len > 1; len -= 2) {
+ /* Keep byte order ! */
+ isp116x_raw_write_data16(isp116x, cpu_to_le16(*dp2++));
+ }
+
if (len)
isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
}
@@ -124,6 +131,10 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
u16 w;
int quot = len % 4;
+ /* buffer is already in 'usb data order', which is LE. */
+ /* When reading buffer as u16, we have to take care byte order */
+ /* doesn't get mixed up */
+
if ((unsigned long)dp2 & 1) {
/* not aligned */
for (; len > 1; len -= 2) {
@@ -131,12 +142,16 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
*dp++ = w & 0xff;
*dp++ = (w >> 8) & 0xff;
}
+
if (len)
*dp = 0xff & isp116x_read_data16(isp116x);
} else {
/* aligned */
- for (; len > 1; len -= 2)
- *dp2++ = isp116x_raw_read_data16(isp116x);
+ for (; len > 1; len -= 2) {
+ /* Keep byte order! */
+ *dp2++ = le16_to_cpu(isp116x_raw_read_data16(isp116x));
+ }
+
if (len)
*(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
}
@@ -1592,7 +1607,7 @@ static int __devinit isp116x_probe(struct platform_device *pdev)
}
/* allocate and initialize hcd */
- hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
ret = -ENOMEM;
goto err5;
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index 65aa5ecf569..c858f2adb92 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -38,6 +38,7 @@ struct isp1760_hcd {
unsigned i_thresh;
unsigned long reset_done;
unsigned long next_statechange;
+ unsigned int devflags;
};
static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
@@ -378,9 +379,31 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
int result;
- u32 scratch;
+ u32 scratch, hwmode;
+
+ /* Setup HW Mode Control: This assumes a level active-low interrupt */
+ hwmode = HW_DATA_BUS_32BIT;
+
+ if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16)
+ hwmode &= ~HW_DATA_BUS_32BIT;
+ if (priv->devflags & ISP1760_FLAG_ANALOG_OC)
+ hwmode |= HW_ANA_DIGI_OC;
+ if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH)
+ hwmode |= HW_DACK_POL_HIGH;
+ if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
+ hwmode |= HW_DREQ_POL_HIGH;
+
+ /*
+ * We have to set this first in case we're in 16-bit mode.
+ * Write it twice to ensure correct upper bits if switching
+ * to 16-bit mode.
+ */
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+ /* Change bus pattern */
+ scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
if (scratch != 0xdeadbabe) {
printk(KERN_ERR "ISP1760: Scratch test failed.\n");
@@ -403,17 +426,29 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
/* Step 11 passed */
- isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
- isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+ isp1760_info(priv, "bus width: %d, oc: %s\n",
+ (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
+ 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
+ "analog" : "digital");
/* ATL reset */
- scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
- isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
mdelay(10);
- isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
- isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL);
- mdelay(10);
+ isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
+ isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+
+ /*
+ * PORT 1 Control register of the ISP1760 is the OTG control
+ * register on ISP1761.
+ */
+ if (!(priv->devflags & ISP1760_FLAG_ISP1761) &&
+ !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) {
+ isp1760_writel(PORT1_POWER | PORT1_INIT2,
+ hcd->regs + HC_PORT1_CTRL);
+ mdelay(10);
+ }
priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
@@ -453,8 +488,7 @@ static int isp1760_run(struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
isp1760_enable_interrupts(hcd);
temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
- temp |= FINAL_HW_CONFIG;
- isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
command = isp1760_readl(hcd->regs + HC_USBCMD);
command &= ~(CMD_LRESET|CMD_RESET);
@@ -782,8 +816,8 @@ static void enqueue_one_int_qtd(u32 int_regs, u32 payload,
qtd->status |= slot << 16;
}
-void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
- struct isp1760_qtd *qtd)
+static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+ struct isp1760_qtd *qtd)
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
u32 skip_map, or_map;
@@ -816,8 +850,8 @@ void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
}
-void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
- struct isp1760_qtd *qtd)
+static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+ struct isp1760_qtd *qtd)
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
u32 skip_map, or_map;
@@ -1592,7 +1626,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
struct inter_packet_info *ints;
u32 i;
u32 reg_base, or_reg, skip_reg;
- int flags;
+ unsigned long flags;
struct ptd ptd;
switch (usb_pipetype(urb->pipe)) {
@@ -2061,7 +2095,7 @@ static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
struct isp1760_qh *qh;
struct isp1760_qtd *qtd;
- u32 flags;
+ unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
qh = ep->hcpriv;
@@ -2112,6 +2146,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd)
static void isp1760_stop(struct usb_hcd *hcd)
{
struct isp1760_hcd *priv = hcd_to_priv(hcd);
+ u32 temp;
isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1,
NULL, 0);
@@ -2120,7 +2155,8 @@ static void isp1760_stop(struct usb_hcd *hcd)
spin_lock_irq(&priv->lock);
ehci_reset(priv);
/* Disable IRQ */
- isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+ temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
spin_unlock_irq(&priv->lock);
isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
@@ -2128,10 +2164,11 @@ static void isp1760_stop(struct usb_hcd *hcd)
static void isp1760_shutdown(struct usb_hcd *hcd)
{
- u32 command;
+ u32 command, temp;
isp1760_stop(hcd);
- isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+ temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+ isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
command = isp1760_readl(hcd->regs + HC_USBCMD);
command &= ~CMD_RUN;
@@ -2183,7 +2220,8 @@ void deinit_kmem_cache(void)
}
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
- u64 irqflags, struct device *dev, const char *busname)
+ u64 irqflags, struct device *dev, const char *busname,
+ unsigned int devflags)
{
struct usb_hcd *hcd;
struct isp1760_hcd *priv;
@@ -2195,11 +2233,12 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
/* prevent usb-core allocating DMA pages */
dev->dma_mask = NULL;
- hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev->bus_id);
+ hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev_name(dev));
if (!hcd)
return ERR_PTR(-ENOMEM);
priv = hcd_to_priv(hcd);
+ priv->devflags = devflags;
init_memory(priv);
hcd->regs = ioremap(res_start, res_len);
if (!hcd->regs) {
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index 3d86d0f6b14..6473dd86993 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -3,7 +3,8 @@
/* exports for if */
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
- u64 irqflags, struct device *dev, const char *busname);
+ u64 irqflags, struct device *dev, const char *busname,
+ unsigned int devflags);
int init_kmem_once(void);
void deinit_kmem_cache(void);
@@ -31,6 +32,7 @@ void deinit_kmem_cache(void);
/* Configuration Register */
#define HC_HW_MODE_CTRL 0x300
#define ALL_ATX_RESET (1 << 31)
+#define HW_ANA_DIGI_OC (1 << 15)
#define HW_DATA_BUS_32BIT (1 << 8)
#define HW_DACK_POL_HIGH (1 << 6)
#define HW_DREQ_POL_HIGH (1 << 5)
@@ -56,13 +58,14 @@ void deinit_kmem_cache(void);
#define PORT1_POWER (3 << 3)
#define PORT1_INIT1 (1 << 7)
#define PORT1_INIT2 (1 << 23)
+#define HW_OTG_CTRL_SET 0x374
+#define HW_OTG_CTRL_CLR 0x376
/* Interrupt Register */
#define HC_INTERRUPT_REG 0x310
#define HC_INTERRUPT_ENABLE 0x314
#define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
-#define FINAL_HW_CONFIG (HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT)
#define HC_ISO_INT (1 << 9)
#define HC_ATL_INT (1 << 8)
@@ -122,6 +125,19 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
#define isp1760_err(priv, fmt, args...) \
dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
+/*
+ * Device flags that can vary from board to board. All of these
+ * indicate the most "atypical" case, so that a devflags of 0 is
+ * a sane default configuration.
+ */
+#define ISP1760_FLAG_PORT1_DIS 0x00000001 /* Port 1 disabled */
+#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */
+#define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */
+#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */
+#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */
+#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */
+#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */
+
/* chip memory management */
struct memory_chunk {
unsigned int start;
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index c9db3fe9872..051ef7b6bdc 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -35,13 +35,15 @@ static int of_isp1760_probe(struct of_device *dev,
int virq;
u64 res_len;
int ret;
+ const unsigned int *prop;
+ unsigned int devflags = 0;
ret = of_address_to_resource(dp, 0, &memory);
if (ret)
return -ENXIO;
res = request_mem_region(memory.start, memory.end - memory.start + 1,
- dev->dev.bus_id);
+ dev_name(&dev->dev));
if (!res)
return -EBUSY;
@@ -55,8 +57,32 @@ static int of_isp1760_probe(struct of_device *dev,
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
+ if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
+ devflags |= ISP1760_FLAG_ISP1761;
+
+ if (of_get_property(dp, "port1-disable", NULL) != NULL)
+ devflags |= ISP1760_FLAG_PORT1_DIS;
+
+ /* Some systems wire up only 16 of the 32 data lines */
+ prop = of_get_property(dp, "bus-width", NULL);
+ if (prop && *prop == 16)
+ devflags |= ISP1760_FLAG_BUS_WIDTH_16;
+
+ if (of_get_property(dp, "port1-otg", NULL) != NULL)
+ devflags |= ISP1760_FLAG_OTG_EN;
+
+ if (of_get_property(dp, "analog-oc", NULL) != NULL)
+ devflags |= ISP1760_FLAG_ANALOG_OC;
+
+ if (of_get_property(dp, "dack-polarity", NULL) != NULL)
+ devflags |= ISP1760_FLAG_DACK_POL_HIGH;
+
+ if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
+ devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
+
hcd = isp1760_register(memory.start, res_len, virq,
- IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+ IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+ devflags);
if (IS_ERR(hcd)) {
ret = PTR_ERR(hcd);
goto release_reg;
@@ -87,6 +113,9 @@ static struct of_device_id of_isp1760_match[] = {
{
.compatible = "nxp,usb-isp1760",
},
+ {
+ .compatible = "nxp,usb-isp1761",
+ },
{ },
};
MODULE_DEVICE_TABLE(of, of_isp1760_match);
@@ -116,6 +145,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
int length;
int status = 1;
struct usb_hcd *hcd;
+ unsigned int devflags = 0;
if (usb_disabled())
return -ENODEV;
@@ -200,7 +230,8 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
dev->dev.dma_mask = NULL;
hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
- IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+ IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+ devflags);
pci_set_drvdata(dev, hcd);
if (!hcd)
return 0;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index e534f9de0f0..a5d8e550d89 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -91,7 +91,7 @@ static void at91_stop_hc(struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -184,13 +184,14 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
* context, "rmmod" or something similar.
*
*/
-static int usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void usb_hcd_at91_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
usb_remove_hcd(hcd);
at91_stop_hc(pdev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
if (cpu_is_at91sam9261())
clk_put(hclk);
@@ -199,7 +200,6 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd,
fclk = iclk = hclk = NULL;
dev_set_drvdata(&pdev->dev, NULL);
- return 0;
}
/*-------------------------------------------------------------------------*/
@@ -309,7 +309,8 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
}
device_init_wakeup(&pdev->dev, 0);
- return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
+ usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
+ return 0;
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 68c17f5ea8e..c0948008fe3 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -34,7 +34,8 @@
#ifdef __LITTLE_ENDIAN
#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C)
#elif __BIG_ENDIAN
-#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE)
+#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \
+ USBH_ENABLE_BE)
#else
#error not byte order defined
#endif
@@ -46,213 +47,87 @@
#define USB_MCFG_RDCOMB (1<<30)
#define USB_MCFG_SSDEN (1<<23)
#define USB_MCFG_OHCCLKEN (1<<16)
+#ifdef CONFIG_DMA_COHERENT
#define USB_MCFG_UCAM (1<<7)
+#else
+#define USB_MCFG_UCAM (0)
+#endif
#define USB_MCFG_OBMEN (1<<1)
#define USB_MCFG_OMEMEN (1<<0)
#define USBH_ENABLE_CE USB_MCFG_OHCCLKEN
-#ifdef CONFIG_DMA_COHERENT
-#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \
- | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
- | USB_MCFG_SSDEN | USB_MCFG_UCAM \
- | USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
-#else
-#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \
- | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
- | USB_MCFG_SSDEN \
- | USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
-#endif
+
+#define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \
+ USBH_ENABLE_CE | USB_MCFG_SSDEN | \
+ USB_MCFG_UCAM | \
+ USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
+
#define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
#endif /* Au1200 */
extern int usb_disabled(void);
-/*-------------------------------------------------------------------------*/
-
-static void au1xxx_start_ohc(struct platform_device *dev)
+static void au1xxx_start_ohc(void)
{
- printk(KERN_DEBUG __FILE__
- ": starting Au1xxx OHCI USB Controller\n");
-
/* enable host controller */
-
#ifndef CONFIG_SOC_AU1200
-
au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG);
+ au_sync();
udelay(1000);
- au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG);
- udelay(1000);
-
-#else /* Au1200 */
- /* write HW defaults again in case Yamon cleared them */
- if (au_readl(USB_HOST_CONFIG) == 0) {
- au_writel(0x00d02000, USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
- udelay(1000);
- }
- au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
+ au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+ au_sync();
udelay(1000);
- au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
- udelay(1000);
-
-#endif /* Au1200 */
-#ifndef CONFIG_SOC_AU1200
/* wait for reset complete (read register twice; see au1500 errata) */
while (au_readl(USB_HOST_CONFIG),
!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
-#endif
udelay(1000);
- printk(KERN_DEBUG __FILE__
- ": Clock to USB host has been enabled \n");
-}
-
-static void au1xxx_stop_ohc(struct platform_device *dev)
-{
- printk(KERN_DEBUG __FILE__
- ": stopping Au1xxx OHCI USB Controller\n");
-
-#ifndef CONFIG_SOC_AU1200
-
- /* Disable clock */
- au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
-
#else /* Au1200 */
-
- /* Disable mem */
- au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
+ au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG);
+ au_sync();
udelay(1000);
- /* Disable clock */
- au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
- au_readl(USB_HOST_CONFIG);
+
+ au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+ au_sync();
+ udelay(2000);
#endif /* Au1200 */
}
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-static int usb_ohci_au1xxx_probe(const struct hc_driver *driver,
- struct platform_device *dev)
+static void au1xxx_stop_ohc(void)
{
- int retval;
- struct usb_hcd *hcd;
-
-#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
- /* Au1200 AB USB does not support coherent memory */
- if (!(read_c0_prid() & 0xff)) {
- pr_info("%s: this is chip revision AB !!\n",
- dev->name);
- pr_info("%s: update your board or re-configure the kernel\n",
- dev->name);
- return -ENODEV;
- }
+#ifdef CONFIG_SOC_AU1200
+ /* Disable mem */
+ au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG);
+ au_sync();
+ udelay(1000);
#endif
-
- if (dev->resource[1].flags != IORESOURCE_IRQ) {
- pr_debug("resource[1] is not IORESOURCE_IRQ\n");
- return -ENOMEM;
- }
-
- hcd = usb_create_hcd(driver, &dev->dev, "au1xxx");
- if (!hcd)
- return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
- if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
- pr_debug("request_mem_region failed\n");
- retval = -EBUSY;
- goto err1;
- }
-
- hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- pr_debug("ioremap failed\n");
- retval = -ENOMEM;
- goto err2;
- }
-
- au1xxx_start_ohc(dev);
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED);
- if (retval == 0)
- return retval;
-
- au1xxx_stop_ohc(dev);
- iounmap(hcd->regs);
- err2:
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
- usb_put_hcd(hcd);
- return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_au1xxx_probe(), first invoking
- * the HCD's stop() method. It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev)
-{
- usb_remove_hcd(hcd);
- au1xxx_stop_ohc(dev);
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- usb_put_hcd(hcd);
+ /* Disable clock */
+ au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+ au_sync();
}
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_au1xxx_start (struct usb_hcd *hcd)
+static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
- ohci_dbg (ohci, "ohci_au1xxx_start, ohci:%p", ohci);
+ ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
- if ((ret = ohci_init (ohci)) < 0)
+ if ((ret = ohci_init(ohci)) < 0)
return ret;
- if ((ret = ohci_run (ohci)) < 0) {
+ if ((ret = ohci_run(ohci)) < 0) {
err ("can't start %s", hcd->self.bus_name);
- ohci_stop (hcd);
+ ohci_stop(hcd);
return ret;
}
return 0;
}
-/*-------------------------------------------------------------------------*/
-
static const struct hc_driver ohci_au1xxx_hc_driver = {
.description = hcd_name,
.product_desc = "Au1xxx OHCI",
@@ -296,18 +171,66 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
.start_port_reset = ohci_start_port_reset,
};
-/*-------------------------------------------------------------------------*/
-
static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
{
int ret;
-
- pr_debug ("In ohci_hcd_au1xxx_drv_probe");
+ struct usb_hcd *hcd;
if (usb_disabled())
return -ENODEV;
- ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev);
+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
+ /* Au1200 AB USB does not support coherent memory */
+ if (!(read_c0_prid() & 0xff)) {
+ printk(KERN_INFO "%s: this is chip revision AB !!\n",
+ pdev->name);
+ printk(KERN_INFO "%s: update your board or re-configure "
+ "the kernel\n", pdev->name);
+ return -ENODEV;
+ }
+#endif
+
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug("resource[1] is not IORESOURCE_IRQ\n");
+ return -ENOMEM;
+ }
+
+ hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
+ if (!hcd)
+ return -ENOMEM;
+
+ hcd->rsrc_start = pdev->resource[0].start;
+ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug("request_mem_region failed\n");
+ ret = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed\n");
+ ret = -ENOMEM;
+ goto err2;
+ }
+
+ au1xxx_start_ohc();
+ ohci_hcd_init(hcd_to_ohci(hcd));
+
+ ret = usb_add_hcd(hcd, pdev->resource[1].start,
+ IRQF_DISABLED | IRQF_SHARED);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, hcd);
+ return ret;
+ }
+
+ au1xxx_stop_ohc();
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
return ret;
}
@@ -315,30 +238,78 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- usb_ohci_au1xxx_remove(hcd, pdev);
+ usb_remove_hcd(hcd);
+ au1xxx_stop_ohc();
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+ platform_set_drvdata(pdev, NULL);
+
return 0;
}
- /*TBD*/
-/*static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *dev)
+
+#ifdef CONFIG_PM
+static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
+ pm_message_t message)
{
- struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ unsigned long flags;
+ int rc;
+
+ rc = 0;
+
+ /* Root hub was already suspended. Disable irq emission and
+ * mark HW unaccessible, bail out if RH has been resumed. Use
+ * the spinlock to properly synchronize with possible pending
+ * RH suspend or resume activity.
+ *
+ * This is still racy as hcd->state is manipulated outside of
+ * any locks =P But that will be a different fix.
+ */
+ spin_lock_irqsave(&ohci->lock, flags);
+ if (hcd->state != HC_STATE_SUSPENDED) {
+ rc = -EINVAL;
+ goto bail;
+ }
+ ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+ (void)ohci_readl(ohci, &ohci->regs->intrdisable);
- return 0;
+ /* make sure snapshot being resumed re-enumerates everything */
+ if (message.event == PM_EVENT_PRETHAW)
+ ohci_usb_reset(ohci);
+
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ au1xxx_stop_ohc();
+bail:
+ spin_unlock_irqrestore(&ohci->lock, flags);
+
+ return rc;
}
-static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
+
+static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
{
- struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ au1xxx_start_ohc();
+
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ ohci_finish_controller_resume(hcd);
return 0;
}
-*/
+#else
+#define ohci_hcd_au1xxx_drv_suspend NULL
+#define ohci_hcd_au1xxx_drv_resume NULL
+#endif
static struct platform_driver ohci_hcd_au1xxx_driver = {
.probe = ohci_hcd_au1xxx_drv_probe,
.remove = ohci_hcd_au1xxx_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
- /*.suspend = ohci_hcd_au1xxx_drv_suspend, */
- /*.resume = ohci_hcd_au1xxx_drv_resume, */
+ .suspend = ohci_hcd_au1xxx_drv_suspend,
+ .resume = ohci_hcd_au1xxx_drv_resume,
.driver = {
.name = "au1xxx-ohci",
.owner = THIS_MODULE,
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index e06bfaebec5..7cef1d2f7cc 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -651,7 +651,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
"%s\n"
"%s version " DRIVER_VERSION "\n",
hcd->self.controller->bus->name,
- hcd->self.controller->bus_id,
+ dev_name(hcd->self.controller),
hcd->product_desc,
hcd_name);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a8160d65f32..26bc47941d0 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -974,7 +974,7 @@ MODULE_LICENSE ("GPL");
#define PCI_DRIVER ohci_pci_driver
#endif
-#ifdef CONFIG_SA1111
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111)
#include "ohci-sa1111.c"
#define SA1111_DRIVER ohci_hcd_sa1111_driver
#endif
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index a19a4f80a6e..6e5e5f81ac9 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -329,7 +329,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
}
- hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
goto err0;
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 28b458f20cc..6ad8f2fc57b 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -109,8 +109,6 @@ static struct clk *usb_clk;
static int isp1301_probe(struct i2c_adapter *adap);
static int isp1301_detach(struct i2c_client *client);
-static int isp1301_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
static const unsigned short normal_i2c[] =
{ ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
@@ -123,30 +121,37 @@ static struct i2c_client_address_data addr_data = {
};
struct i2c_driver isp1301_driver = {
- .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "isp1301_pnx",
+ },
.attach_adapter = isp1301_probe,
.detach_client = isp1301_detach,
- .command = isp1301_command
};
static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct i2c_client *c;
+ int err;
c = kzalloc(sizeof(*c), GFP_KERNEL);
-
if (!c)
return -ENOMEM;
- strcpy(c->name, "isp1301");
+ strlcpy(c->name, "isp1301_pnx", I2C_NAME_SIZE);
c->flags = 0;
c->addr = addr;
c->adapter = adap;
c->driver = &isp1301_driver;
+ err = i2c_attach_client(c);
+ if (err) {
+ kfree(c);
+ return err;
+ }
+
isp1301_i2c_client = c;
- return i2c_attach_client(c);
+ return 0;
}
static int isp1301_probe(struct i2c_adapter *adap)
@@ -161,13 +166,6 @@ static int isp1301_detach(struct i2c_client *client)
return 0;
}
-/* No commands defined */
-static int isp1301_command(struct i2c_client *client, unsigned int cmd,
- void *arg)
-{
- return 0;
-}
-
static void i2c_write(u8 buf, u8 subaddr)
{
char tmpbuf[2];
@@ -389,7 +387,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
USB_CLOCK_MASK) ;
- hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
err("Failed to allocate HC buffer");
ret = -ENOMEM;
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index a6725279122..91e6e101a4c 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -14,8 +14,8 @@
*/
#include <linux/signal.h>
+#include <linux/of_platform.h>
-#include <asm/of_platform.h>
#include <asm/prom.h>
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index c1935ae537f..55c95647f00 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -129,7 +129,7 @@ static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
- hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
+ hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev_name(&dev->core));
if (!hcd) {
dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__,
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 9b547407c93..6a9b4c55795 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -159,9 +159,6 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
int branch;
- if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
- return -EAGAIN;
-
ed->state = ED_OPER;
ed->ed_prev = NULL;
ed->ed_next = NULL;
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index e610698c6b6..21b164e4abe 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -143,7 +143,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
goto err2;
}
- hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
goto err2;
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 7275186db31..3660c83d80a 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -113,7 +113,7 @@ static int ssb_ohci_attach(struct ssb_device *dev)
ssb_device_enable(dev, flags);
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
- dev->dev->bus_id);
+ dev_name(dev->dev));
if (!hcd)
goto err_dev_disable;
ohcidev = hcd_to_ssb_ohci(hcd);
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 16667342b3c..d5f02dddb12 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -312,9 +312,9 @@ static void put_child_connect_map(struct r8a66597 *r8a66597, int address)
static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch)
{
u16 pipenum = pipe->info.pipenum;
- unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
- unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
- unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
+ const unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
+ const unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
+ const unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
if (dma_ch > R8A66597_PIPE_NO_DMA) /* dma fifo not use? */
dma_ch = R8A66597_PIPE_NO_DMA;
@@ -863,6 +863,32 @@ static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
dev->dma_map = 0;
}
+static u16 get_interval(struct urb *urb, __u8 interval)
+{
+ u16 time = 1;
+ int i;
+
+ if (urb->dev->speed == USB_SPEED_HIGH) {
+ if (interval > IITV)
+ time = IITV;
+ else
+ time = interval ? interval - 1 : 0;
+ } else {
+ if (interval > 128) {
+ time = IITV;
+ } else {
+ /* calculate the nearest value for PIPEPERI */
+ for (i = 0; i < 7; i++) {
+ if ((1 << i) < interval &&
+ (1 << (i + 1) > interval))
+ time = 1 << i;
+ }
+ }
+ }
+
+ return time;
+}
+
static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
{
__u8 i;
@@ -901,10 +927,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
info.interval = 0;
info.timer_interval = 0;
} else {
- if (ep->bInterval > IITV)
- info.interval = IITV;
- else
- info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
+ info.interval = get_interval(urb, ep->bInterval);
info.timer_interval = get_timer_interval(urb, ep->bInterval);
}
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
@@ -2244,6 +2267,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
struct r8a66597 *r8a66597;
int ret = 0;
int i;
+ unsigned long irq_trigger;
if (pdev->dev.dma_mask) {
ret = -EINVAL;
@@ -2302,7 +2326,11 @@ static int __init r8a66597_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&r8a66597->child_device);
hcd->rsrc_start = res->start;
- ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+ if (irq_sense == INTL)
+ irq_trigger = IRQF_TRIGGER_LOW;
+ else
+ irq_trigger = IRQF_TRIGGER_FALLING;
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger);
if (ret != 0) {
err("Failed to add hcd");
goto clean_up;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 426575247b2..340d72da554 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1674,7 +1674,7 @@ sl811h_probe(struct platform_device *dev)
}
/* allocate and initialize hcd */
- hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev->dev.bus_id);
+ hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev_name(&dev->dev));
if (!hcd) {
retval = -ENOMEM;
goto err5;
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 9b6323f768b..20ad3c48fcb 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -3124,7 +3124,7 @@ static int __devinit u132_probe(struct platform_device *pdev)
if (pdev->dev.dma_mask)
return -EINVAL;
- hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+ hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
);
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 8e4427aebb1..885b585360b 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -12,7 +12,7 @@
* (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
*/
-static __u8 root_hub_hub_des[] =
+static const __u8 root_hub_hub_des[] =
{
0x09, /* __u8 bLength; */
0x29, /* __u8 bDescriptorType; Hub-descriptor */
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 09393869742..d2f61d5510e 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -1421,7 +1421,8 @@ ofail: mutex_unlock(&cp->mutex);
/* IOCTL functions */
-static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long auerchar_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
pauerchar_t ccp = (pauerchar_t) file->private_data;
int ret = 0;
@@ -1452,7 +1453,7 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
mutex_unlock(&ccp->mutex);
return -ENODEV;
}
-
+ lock_kernel();
switch (cmd) {
/* return != 0 if Transmitt channel ready to send */
@@ -1547,9 +1548,10 @@ static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int
default:
dbg ("IOCTL_AU_UNKNOWN");
- ret = -ENOIOCTLCMD;
+ ret = -ENOTTY;
break;
}
+ unlock_kernel();
/* release the mutexes */
mutex_unlock(&cp->mutex);
mutex_unlock(&ccp->mutex);
@@ -1860,7 +1862,7 @@ static const struct file_operations auerswald_fops =
.llseek = no_llseek,
.read = auerchar_read,
.write = auerchar_write,
- .ioctl = auerchar_ioctl,
+ .unlocked_ioctl = auerchar_ioctl,
.open = auerchar_open,
.release = auerchar_release,
};
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 20886c21e73..5d859ded5bb 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -6,8 +6,6 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, as published by
* the Free Software Foundation, version 2.
- *
- * $Id: emi62.c,v 1.15 2002/04/23 06:13:59 tapio Exp $
*/
#include <linux/kernel.h>
#include <linux/errno.h>
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index ec88b3bfee4..97c28097153 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -656,29 +656,6 @@ static int ftdi_elan_release(struct inode *inode, struct file *file)
}
-#define FTDI_ELAN_IOC_MAGIC 0xA1
-#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132)
-static int ftdi_elan_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case FTDI_ELAN_IOCDEBUG:{
- char line[132];
- int size = strncpy_from_user(line,
- (const char __user *)arg, sizeof(line));
- if (size < 0) {
- return -EINVAL;
- } else {
- printk(KERN_ERR "TODO: ioctl %s\n", line);
- return 0;
- }
- }
- default:
- return -EFAULT;
- }
-}
-
-
/*
*
* blocking bulk reads are used to get data from the device
@@ -1222,7 +1199,6 @@ error_1:
static const struct file_operations ftdi_elan_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .ioctl = ftdi_elan_ioctl,
.read = ftdi_elan_read,
.write = ftdi_elan_write,
.open = ftdi_elan_open,
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 1cb54a28347..e6ca9979e3a 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -474,8 +474,8 @@ exit:
/**
* iowarrior_ioctl
*/
-static int iowarrior_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long iowarrior_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
struct iowarrior *dev = NULL;
__u8 *buffer;
@@ -493,6 +493,7 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file,
return -ENOMEM;
/* lock this object */
+ lock_kernel();
mutex_lock(&dev->mutex);
/* verify that the device wasn't unplugged */
@@ -584,6 +585,7 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file,
error_out:
/* unlock the device */
mutex_unlock(&dev->mutex);
+ unlock_kernel();
kfree(buffer);
return retval;
}
@@ -719,7 +721,7 @@ static const struct file_operations iowarrior_fops = {
.owner = THIS_MODULE,
.write = iowarrior_write,
.read = iowarrior_read,
- .ioctl = iowarrior_ioctl,
+ .unlocked_ioctl = iowarrior_ioctl,
.open = iowarrior_open,
.release = iowarrior_release,
.poll = iowarrior_poll,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 330c18e390b..248a12aacef 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -104,9 +104,7 @@ static int close_rio(struct inode *inode, struct file *file)
return 0;
}
-static int
-ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
{
struct RioCommand rio_cmd;
struct rio_usb_data *rio = &rio_instance;
@@ -116,6 +114,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
int retries;
int retval=0;
+ lock_kernel();
mutex_lock(&(rio->lock));
/* Sanity check to make sure rio is connected, powered, etc */
if (rio->present == 0 || rio->rio_dev == NULL) {
@@ -254,6 +253,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
err_out:
mutex_unlock(&(rio->lock));
+ unlock_kernel();
return retval;
}
@@ -433,7 +433,7 @@ file_operations usb_rio_fops = {
.owner = THIS_MODULE,
.read = read_rio,
.write = write_rio,
- .ioctl = ioctl_rio,
+ .unlocked_ioctl = ioctl_rio,
.open = open_rio,
.release = close_rio,
};
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 33182f4c226..fbace41a7cb 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2982,9 +2982,8 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
return retval;
}
-static int
-sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long
+sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct sisusb_usb_data *sisusb;
struct sisusb_info x;
@@ -2995,6 +2994,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
return -ENODEV;
+ lock_kernel();
mutex_lock(&sisusb->lock);
/* Sanity check */
@@ -3053,6 +3053,7 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
err_out:
mutex_unlock(&sisusb->lock);
+ unlock_kernel();
return retval;
}
@@ -3066,9 +3067,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case SISUSB_GET_CONFIG_SIZE:
case SISUSB_GET_CONFIG:
case SISUSB_COMMAND:
- lock_kernel();
- retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
- unlock_kernel();
+ retval = sisusb_ioctl(f, cmd, arg);
return retval;
default:
@@ -3087,7 +3086,7 @@ static const struct file_operations usb_sisusb_fops = {
#ifdef SISUSB_NEW_CONFIG_COMPAT
.compat_ioctl = sisusb_compat_ioctl,
#endif
- .ioctl = sisusb_ioctl
+ .unlocked_ioctl = sisusb_ioctl
};
static struct usb_class_driver usb_sisusb_class = {
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 7f7021ee418..2db4228fbb0 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -146,7 +146,7 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, l
return retval;
}
-static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct usb_lcd *dev;
u16 bcdDevice;
@@ -158,12 +158,14 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
+ lock_kernel();
bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
sprintf(buf,"%1d%1d.%1d%1d",
(bcdDevice & 0xF000)>>12,
(bcdDevice & 0xF00)>>8,
(bcdDevice & 0xF0)>>4,
(bcdDevice & 0xF));
+ unlock_kernel();
if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
@@ -272,7 +274,7 @@ static const struct file_operations lcd_fops = {
.read = lcd_read,
.write = lcd_write,
.open = lcd_open,
- .ioctl = lcd_ioctl,
+ .unlocked_ioctl = lcd_ioctl,
.release = lcd_release,
};
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 293a46247c3..6566fc0a322 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1162,8 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
if (minor >= MON_BIN_MAX_MINOR)
return 0;
- dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
- MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+ dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
+ MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+ "usbmon%d", minor);
if (IS_ERR(dev))
return 0;
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index c7a595cd648..ac8b0d5ce7f 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/usb.h>
+#include <linux/fs.h>
#include <asm/uaccess.h>
#include "usb_mon.h"
@@ -42,19 +43,8 @@ static ssize_t mon_stat_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct snap *sp = file->private_data;
- loff_t pos = *ppos;
- int cnt;
- if (pos < 0 || pos >= sp->slen)
- return 0;
- if (nbytes == 0)
- return 0;
- if ((cnt = sp->slen - pos) > nbytes)
- cnt = nbytes;
- if (copy_to_user(buf, sp->str + pos, cnt))
- return -EFAULT;
- *ppos = pos + cnt;
- return cnt;
+ return simple_read_from_buffer(buf, nbytes, ppos, sp->str, sp->slen);
}
static int mon_stat_release(struct inode *inode, struct file *file)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 9a7681b5526..8878c1767fc 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -64,14 +64,6 @@ config USB_SERIAL_AIRCABLE
To compile this driver as a module, choose M here: the module
will be called aircable.
-config USB_SERIAL_AIRPRIME
- tristate "USB AirPrime CDMA Wireless Driver"
- help
- Say Y here if you want to use a AirPrime CDMA Wireless PC card.
-
- To compile this driver as a module, choose M here: the
- module will be called airprime.
-
config USB_SERIAL_ARK3116
tristate "USB ARK Micro 3116 USB Serial Driver"
help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 17a762ab676..6047f818adf 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -12,7 +12,6 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o
-obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index db6f97a93c0..79ea98c66fa 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work)
* 64 bytes, to ensure I do not get throttled.
* Ask USB mailing list for better aproach.
*/
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
schedule_work(&priv->rx_work);
@@ -378,13 +378,14 @@ static void aircable_shutdown(struct usb_serial *serial)
}
}
-static int aircable_write_room(struct usb_serial_port *port)
+static int aircable_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
return serial_buf_data_avail(priv->tx_buf);
}
-static int aircable_write(struct usb_serial_port *port,
+static int aircable_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *source, int count)
{
struct aircable_private *priv = usb_get_serial_port_data(port);
@@ -466,7 +467,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
if (status) {
dbg("%s - urb status = %d", __func__, status);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port is closed, exiting.", __func__);
return;
}
@@ -494,7 +495,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, urb->transfer_buffer);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
if (urb->actual_length <= 2) {
/* This is an incomplete package */
@@ -528,7 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
@@ -547,8 +548,9 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
/* Based on ftdi_sio.c throttle */
-static void aircable_throttle(struct usb_serial_port *port)
+static void aircable_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -560,8 +562,9 @@ static void aircable_throttle(struct usb_serial_port *port)
}
/* Based on ftdi_sio.c unthrottle */
-static void aircable_unthrottle(struct usb_serial_port *port)
+static void aircable_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
deleted file mode 100644
index 0798c14ce78..00000000000
--- a/drivers/usb/serial/airprime.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * AirPrime CDMA Wireless Serial USB driver
- *
- * Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-static struct usb_device_id id_table [] = {
- { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
- { },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-#define URB_TRANSFER_BUFFER_SIZE 4096
-#define NUM_READ_URBS 4
-#define NUM_WRITE_URBS 4
-#define NUM_BULK_EPS 3
-#define MAX_BULK_EPS 6
-
-/* if overridden by the user, then use their value for the size of the
- * read and write urbs, and the number of endpoints */
-static int buffer_size = URB_TRANSFER_BUFFER_SIZE;
-static int endpoints = NUM_BULK_EPS;
-static int debug;
-struct airprime_private {
- spinlock_t lock;
- int outstanding_urbs;
- int throttled;
- struct urb *read_urbp[NUM_READ_URBS];
-
- /* Settings for the port */
- int rts_state; /* Handshaking pins (outputs) */
- int dtr_state;
- int cts_state; /* Handshaking pins (inputs) */
- int dsr_state;
- int dcd_state;
- int ri_state;
-};
-
-static int airprime_send_setup(struct usb_serial_port *port)
-{
- struct usb_serial *serial = port->serial;
- struct airprime_private *priv;
-
- dbg("%s", __func__);
-
- if (port->number != 0)
- return 0;
-
- priv = usb_get_serial_port_data(port);
-
- if (port->tty) {
- int val = 0;
- if (priv->dtr_state)
- val |= 0x01;
- if (priv->rts_state)
- val |= 0x02;
-
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
- }
-
- return 0;
-}
-
-static void airprime_read_bulk_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- unsigned char *data = urb->transfer_buffer;
- struct tty_struct *tty;
- int result;
- int status = urb->status;
-
- dbg("%s - port %d", __func__, port->number);
-
- if (status) {
- dbg("%s - nonzero read bulk status received: %d",
- __func__, status);
- return;
- }
- usb_serial_debug_data(debug, &port->dev, __func__,
- urb->actual_length, data);
-
- tty = port->tty;
- if (tty && urb->actual_length) {
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
- }
-
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
- return;
-}
-
-static void airprime_write_bulk_callback(struct urb *urb)
-{
- struct usb_serial_port *port = urb->context;
- struct airprime_private *priv = usb_get_serial_port_data(port);
- int status = urb->status;
- unsigned long flags;
-
- dbg("%s - port %d", __func__, port->number);
-
- /* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree(urb->transfer_buffer);
-
- if (status)
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- spin_lock_irqsave(&priv->lock, flags);
- --priv->outstanding_urbs;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- usb_serial_port_softint(port);
-}
-
-static int airprime_open(struct usb_serial_port *port, struct file *filp)
-{
- struct airprime_private *priv = usb_get_serial_port_data(port);
- struct usb_serial *serial = port->serial;
- struct urb *urb;
- char *buffer = NULL;
- int i;
- int result = 0;
-
- dbg("%s - port %d", __func__, port->number);
-
- /* initialize our private data structure if it isn't already created */
- if (!priv) {
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- result = -ENOMEM;
- goto out;
- }
- spin_lock_init(&priv->lock);
- usb_set_serial_port_data(port, priv);
- }
-
- /* Set some sane defaults */
- priv->rts_state = 1;
- priv->dtr_state = 1;
-
- for (i = 0; i < NUM_READ_URBS; ++i) {
- buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer) {
- dev_err(&port->dev, "%s - out of memory.\n",
- __func__);
- result = -ENOMEM;
- goto errout;
- }
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb) {
- kfree(buffer);
- dev_err(&port->dev, "%s - no more urbs?\n",
- __func__);
- result = -ENOMEM;
- goto errout;
- }
- usb_fill_bulk_urb(urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- buffer, buffer_size,
- airprime_read_bulk_callback, port);
- result = usb_submit_urb(urb, GFP_KERNEL);
- if (result) {
- usb_free_urb(urb);
- kfree(buffer);
- dev_err(&port->dev,
- "%s - failed submitting read urb %d for port %d, error %d\n",
- __func__, i, port->number, result);
- goto errout;
- }
- /* remember this urb so we can kill it when the
- port is closed */
- priv->read_urbp[i] = urb;
- }
-
- airprime_send_setup(port);
-
- goto out;
-
- errout:
- /* some error happened, cancel any submitted urbs and clean up
- anything that got allocated successfully */
-
- while (i-- != 0) {
- urb = priv->read_urbp[i];
- buffer = urb->transfer_buffer;
- usb_kill_urb(urb);
- usb_free_urb(urb);
- kfree(buffer);
- }
-
- out:
- return result;
-}
-
-static void airprime_close(struct usb_serial_port *port, struct file *filp)
-{
- struct airprime_private *priv = usb_get_serial_port_data(port);
- int i;
-
- dbg("%s - port %d", __func__, port->number);
-
- priv->rts_state = 0;
- priv->dtr_state = 0;
-
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected)
- airprime_send_setup(port);
- mutex_unlock(&port->serial->disc_mutex);
-
- for (i = 0; i < NUM_READ_URBS; ++i) {
- usb_kill_urb(priv->read_urbp[i]);
- kfree(priv->read_urbp[i]->transfer_buffer);
- usb_free_urb(priv->read_urbp[i]);
- }
-
- /* free up private structure */
- kfree(priv);
- usb_set_serial_port_data(port, NULL);
-}
-
-static int airprime_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
-{
- struct airprime_private *priv = usb_get_serial_port_data(port);
- struct usb_serial *serial = port->serial;
- struct urb *urb;
- unsigned char *buffer;
- unsigned long flags;
- int status;
- dbg("%s - port %d", __func__, port->number);
-
- spin_lock_irqsave(&priv->lock, flags);
- if (priv->outstanding_urbs > NUM_WRITE_URBS) {
- spin_unlock_irqrestore(&priv->lock, flags);
- dbg("%s - write limit hit\n", __func__);
- return 0;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
- buffer = kmalloc(count, GFP_ATOMIC);
- if (!buffer) {
- dev_err(&port->dev, "out of memory\n");
- return -ENOMEM;
- }
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- dev_err(&port->dev, "no more free urbs\n");
- kfree(buffer);
- return -ENOMEM;
- }
- memcpy(buffer, buf, count);
-
- usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
-
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- buffer, count,
- airprime_write_bulk_callback, port);
-
- /* send it down the pipe */
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status) {
- dev_err(&port->dev,
- "%s - usb_submit_urb(write bulk) failed with status = %d\n",
- __func__, status);
- count = status;
- kfree(buffer);
- } else {
- spin_lock_irqsave(&priv->lock, flags);
- ++priv->outstanding_urbs;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
- /* we are done with this urb, so let the host driver
- * really free it when it is finished with it */
- usb_free_urb(urb);
- return count;
-}
-
-static struct usb_driver airprime_driver = {
- .name = "airprime",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
-};
-
-static struct usb_serial_driver airprime_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "airprime",
- },
- .usb_driver = &airprime_driver,
- .id_table = id_table,
- .open = airprime_open,
- .close = airprime_close,
- .write = airprime_write,
-};
-
-static int __init airprime_init(void)
-{
- int retval;
-
- airprime_device.num_ports = endpoints;
- if (endpoints < 0 || endpoints >= MAX_BULK_EPS)
- airprime_device.num_ports = NUM_BULK_EPS;
-
- retval = usb_serial_register(&airprime_device);
- if (retval)
- return retval;
- retval = usb_register(&airprime_driver);
- if (retval)
- usb_serial_deregister(&airprime_device);
- return retval;
-}
-
-static void __exit airprime_exit(void)
-{
- dbg("%s", __func__);
-
- usb_deregister(&airprime_driver);
- usb_serial_deregister(&airprime_device);
-}
-
-module_init(airprime_init);
-module_exit(airprime_exit);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled");
-module_param(buffer_size, int, 0);
-MODULE_PARM_DESC(buffer_size,
- "Size of the transfer buffers in bytes (default 4096)");
-module_param(endpoints, int, 0);
-MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 77895c8f8f3..aec61880f36 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -158,12 +158,13 @@ cleanup:
return -ENOMEM;
}
-static void ark3116_set_termios(struct usb_serial_port *port,
+static void ark3116_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned long flags;
int baud;
@@ -177,8 +178,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B9600 | CS8
+ *termios = tty_std_termios;
+ termios->c_cflag = B9600 | CS8
| CREAD | HUPCL | CLOCAL;
termios->c_ispeed = 9600;
termios->c_ospeed = 9600;
@@ -192,7 +193,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc");
- *port->tty->termios = *old_termios;
+ *termios = *old_termios;
return;
}
@@ -243,7 +244,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
}
/* set baudrate */
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
switch (baud) {
case 75:
@@ -262,11 +263,11 @@ static void ark3116_set_termios(struct usb_serial_port *port,
case 230400:
case 460800:
/* Report the resulting rate back to the caller */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
break;
/* set 9600 as default (if given baudrate is invalid for example) */
default:
- tty_encode_baud_rate(port->tty, 9600, 9600);
+ tty_encode_baud_rate(tty, 9600, 9600);
case 0:
baud = 9600;
}
@@ -317,7 +318,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
return;
}
-static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -332,7 +334,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
return -ENOMEM;
}
- result = usb_serial_generic_open(port, filp);
+ result = usb_serial_generic_open(tty, port, filp);
if (result)
goto err_out;
@@ -362,8 +364,8 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
/* initialise termios */
- if (port->tty)
- ark3116_set_termios(port, &tmp_termios);
+ if (tty)
+ ark3116_set_termios(tty, port, &tmp_termios);
err_out:
kfree(buf);
@@ -371,9 +373,10 @@ err_out:
return result;
}
-static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
@@ -403,8 +406,9 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
char *buf;
char temp;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 0a322fc53d6..2ebe06c3405 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -7,13 +7,14 @@
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
- *
+ *
* 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.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* TODO:
* -- Add true modem contol line query capability. Currently we track the
@@ -28,7 +29,8 @@
* compressed all the differnent device entries into 1.
*
* 30-May-2001 gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* 08-Apr-2001 gb
* - Identify version on module load.
@@ -41,7 +43,7 @@
* - Added support for the old Belkin and Peracom devices.
* - Made the port able to be opened multiple times.
* - Added some defaults incase the line settings are things these devices
- * can't support.
+ * can't support.
*
* 18-Oct-2000 William Greathouse
* Released into the wild (linux-usb-devel)
@@ -72,7 +74,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "belkin_sa.h"
@@ -87,16 +89,19 @@ static int debug;
#define DRIVER_DESC "USB Belkin Serial converter driver"
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int belkin_sa_startup (struct usb_serial *serial);
-static void belkin_sa_shutdown (struct usb_serial *serial);
-static int belkin_sa_open (struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close (struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
-static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file);
-static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+static int belkin_sa_startup(struct usb_serial *serial);
+static void belkin_sa_shutdown(struct usb_serial *serial);
+static int belkin_sa_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_read_int_callback(struct urb *urb);
+static void belkin_sa_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios * old);
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
+static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
+static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
static struct usb_device_id id_table_combined [] = {
@@ -106,10 +111,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
{ USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
- { } /* Terminating entry */
+ { } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver belkin_driver = {
.name = "belkin",
@@ -131,8 +136,8 @@ static struct usb_serial_driver belkin_device = {
.num_ports = 1,
.open = belkin_sa_open,
.close = belkin_sa_close,
- .read_int_callback = belkin_sa_read_int_callback, /* How we get the status info */
- .ioctl = belkin_sa_ioctl,
+ .read_int_callback = belkin_sa_read_int_callback,
+ /* How we get the status info */
.set_termios = belkin_sa_set_termios,
.break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
@@ -160,12 +165,12 @@ struct belkin_sa_private {
#define WDR_TIMEOUT 5000 /* default urb timeout */
/* assumes that struct usb_serial *serial is available */
-#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
+#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
(c), BELKIN_SA_SET_REQUEST_TYPE, \
(v), 0, NULL, 0, WDR_TIMEOUT)
/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup (struct usb_serial *serial)
+static int belkin_sa_startup(struct usb_serial *serial)
{
struct usb_device *dev = serial->dev;
struct belkin_sa_private *priv;
@@ -173,32 +178,35 @@ static int belkin_sa_startup (struct usb_serial *serial)
/* allocate the private data structure */
priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
if (!priv)
- return (-1); /* error */
+ return -1; /* error */
/* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
priv->last_msr = 0;
/* see comments at top of file */
- priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
- info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control);
+ priv->bad_flow_control =
+ (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
+ info("bcdDevice: %04x, bfc: %d",
+ le16_to_cpu(dev->descriptor.bcdDevice),
+ priv->bad_flow_control);
init_waitqueue_head(&serial->port[0]->write_wait);
usb_set_serial_port_data(serial->port[0], priv);
-
- return (0);
+
+ return 0;
}
-static void belkin_sa_shutdown (struct usb_serial *serial)
+static void belkin_sa_shutdown(struct usb_serial *serial)
{
struct belkin_sa_private *priv;
int i;
-
- dbg ("%s", __func__);
+
+ dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
kfree(priv);
@@ -206,7 +214,8 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
}
-static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
+static int belkin_sa_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
@@ -235,7 +244,8 @@ exit:
} /* belkin_sa_open */
-static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s port %d", __func__, port->number);
@@ -246,7 +256,7 @@ static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
} /* belkin_sa_close */
-static void belkin_sa_read_int_callback (struct urb *urb)
+static void belkin_sa_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct belkin_sa_private *priv;
@@ -272,7 +282,8 @@ static void belkin_sa_read_int_callback (struct urb *urb)
goto exit;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* Handle known interrupt data */
/* ignore data[0] and data[1] */
@@ -280,7 +291,7 @@ static void belkin_sa_read_int_callback (struct urb *urb)
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[BELKIN_SA_MSR_INDEX];
-
+
/* Record Control Line states */
if (priv->last_msr & BELKIN_SA_MSR_DSR)
priv->control_state |= TIOCM_DSR;
@@ -311,7 +322,7 @@ static void belkin_sa_read_int_callback (struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
- tty = port->tty;
+ tty = port->port.tty;
/* Overrun Error */
if (priv->last_lsr & BELKIN_SA_LSR_OE) {
}
@@ -328,13 +339,14 @@ static void belkin_sa_read_int_callback (struct urb *urb)
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void belkin_sa_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
@@ -347,8 +359,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
unsigned long control_state;
int bad_flow_control;
speed_t baud;
- struct ktermios *termios = port->tty->termios;
-
+ struct ktermios *termios = tty->termios;
+
iflag = termios->c_iflag;
cflag = termios->c_cflag;
@@ -359,25 +371,26 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
control_state = priv->control_state;
bad_flow_control = priv->bad_flow_control;
spin_unlock_irqrestore(&priv->lock, flags);
-
+
old_iflag = old_termios->c_iflag;
old_cflag = old_termios->c_cflag;
/* Set the baud rate */
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
/* reassert DTR and (maybe) RTS on transition from B0 */
- if( (old_cflag&CBAUD) == B0 ) {
+ if ((old_cflag & CBAUD) == B0) {
control_state |= (TIOCM_DTR|TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
err("Set DTR error");
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS))
- if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
+ if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
+ , 1) < 0)
err("Set RTS error");
}
}
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
if (baud) {
urb_value = BELKIN_SA_BAUD(baud);
/* Clip to maximum speed */
@@ -387,12 +400,13 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
baud = BELKIN_SA_BAUD(urb_value);
/* Report the actual baud rate back to the caller */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
err("Set baudrate error");
} else {
/* Disable flow control */
- if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+ if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
+ BELKIN_SA_FLOW_NONE) < 0)
err("Disable flowcontrol error");
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -403,9 +417,10 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
}
/* set the parity */
- if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) {
+ if ((cflag ^ old_cflag) & (PARENB | PARODD)) {
if (cflag & PARENB)
- urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN;
+ urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD
+ : BELKIN_SA_PARITY_EVEN;
else
urb_value = BELKIN_SA_PARITY_NONE;
if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
@@ -413,31 +428,40 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
}
/* set the number of data bits */
- if( (cflag&CSIZE) != (old_cflag&CSIZE) ) {
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
switch (cflag & CSIZE) {
- case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break;
- case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
- case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
- case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
- default: dbg("CSIZE was not CS5-CS8, using default of 8");
- urb_value = BELKIN_SA_DATA_BITS(8);
- break;
+ case CS5:
+ urb_value = BELKIN_SA_DATA_BITS(5);
+ break;
+ case CS6:
+ urb_value = BELKIN_SA_DATA_BITS(6);
+ break;
+ case CS7:
+ urb_value = BELKIN_SA_DATA_BITS(7);
+ break;
+ case CS8:
+ urb_value = BELKIN_SA_DATA_BITS(8);
+ break;
+ default: dbg("CSIZE was not CS5-CS8, using default of 8");
+ urb_value = BELKIN_SA_DATA_BITS(8);
+ break;
}
if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
err("Set data bits error");
}
/* set the number of stop bits */
- if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) {
- urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) : BELKIN_SA_STOP_BITS(1);
- if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0)
+ if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
+ urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2)
+ : BELKIN_SA_STOP_BITS(1);
+ if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
+ urb_value) < 0)
err("Set stop bits error");
}
/* Set flow control */
- if( (iflag&IXOFF) != (old_iflag&IXOFF)
- || (iflag&IXON) != (old_iflag&IXON)
- || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
+ if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
+ ((cflag ^ old_cflag) & CRTSCTS)) {
urb_value = 0;
if ((iflag & IXOFF) || (iflag & IXON))
urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
@@ -463,8 +487,9 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
} /* belkin_sa_set_termios */
-static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
@@ -472,12 +497,13 @@ static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
}
-static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
+static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -488,9 +514,10 @@ static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
}
-static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
+static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
@@ -498,7 +525,7 @@ static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
int retval;
int rts = 0;
int dtr = 0;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -540,29 +567,7 @@ exit:
}
-static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return( 0 );
-
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
-
- default:
- dbg("belkin_sa_ioctl arg not supported - 0x%04x",cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* belkin_sa_ioctl */
-
-
-static int __init belkin_sa_init (void)
+static int __init belkin_sa_init(void)
{
int retval;
retval = usb_serial_register(&belkin_device);
@@ -582,17 +587,17 @@ failed_usb_serial_register:
static void __exit belkin_sa_exit (void)
{
- usb_deregister (&belkin_driver);
- usb_serial_deregister (&belkin_device);
+ usb_deregister(&belkin_driver);
+ usb_serial_deregister(&belkin_device);
}
-module_init (belkin_sa_init);
-module_exit (belkin_sa_exit);
+module_init(belkin_sa_init);
+module_exit(belkin_sa_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h
index 9116b92f462..c66a6730d38 100644
--- a/drivers/usb/serial/belkin_sa.h
+++ b/drivers/usb/serial/belkin_sa.h
@@ -7,13 +7,14 @@
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
* individual credits and copyrights.
- *
+ *
* 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.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* 12-Mar-2001 gkh
* Added GoHubs GO-COM232 device id.
@@ -27,7 +28,7 @@
* adapter, so pardon any stupid mistakes. All of the information
* I am using to write this driver was acquired by using a modified
* UsbSnoop on Windows2000.
- *
+ *
*/
#ifndef __LINUX_USB_SERIAL_BSA_H
@@ -96,20 +97,20 @@
/*
* It seems that the interrupt pipe is closely modelled after the
- * 16550 register layout. This is probably because the adapter can
+ * 16550 register layout. This is probably because the adapter can
* be used in a "DOS" environment to simulate a standard hardware port.
*/
-#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */
+#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */
#define BELKIN_SA_LSR_RDR 0x01 /* receive data ready */
#define BELKIN_SA_LSR_OE 0x02 /* overrun error */
#define BELKIN_SA_LSR_PE 0x04 /* parity error */
#define BELKIN_SA_LSR_FE 0x08 /* framing error */
#define BELKIN_SA_LSR_BI 0x10 /* break indicator */
-#define BELKIN_SA_LSR_THE 0x20 /* transmit holding register empty */
+#define BELKIN_SA_LSR_THE 0x20 /* tx holding register empty */
#define BELKIN_SA_LSR_TE 0x40 /* transmit register empty */
#define BELKIN_SA_LSR_ERR 0x80 /* OE | PE | FE | BI */
-#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */
+#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */
#define BELKIN_SA_MSR_DCTS 0x01 /* Delta CTS */
#define BELKIN_SA_MSR_DDSR 0x02 /* Delta DSR */
#define BELKIN_SA_MSR_DRI 0x04 /* Delta RI */
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 0b14aea8ebd..83bbb5bca2e 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -15,7 +15,8 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
+static int usb_serial_device_match(struct device *dev,
+ struct device_driver *drv)
{
struct usb_serial_driver *driver;
const struct usb_serial_port *port;
@@ -46,7 +47,7 @@ static ssize_t show_port_number(struct device *dev,
static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL);
-static int usb_serial_device_probe (struct device *dev)
+static int usb_serial_device_probe(struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
@@ -66,7 +67,7 @@ static int usb_serial_device_probe (struct device *dev)
retval = -EIO;
goto exit;
}
- retval = driver->port_probe (port);
+ retval = driver->port_probe(port);
module_put(driver->driver.owner);
if (retval)
goto exit;
@@ -77,8 +78,8 @@ static int usb_serial_device_probe (struct device *dev)
goto exit;
minor = port->number;
- tty_register_device (usb_serial_tty_driver, minor, dev);
- dev_info(&port->serial->dev->dev,
+ tty_register_device(usb_serial_tty_driver, minor, dev);
+ dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d\n",
driver->description, minor);
@@ -86,7 +87,7 @@ exit:
return retval;
}
-static int usb_serial_device_remove (struct device *dev)
+static int usb_serial_device_remove(struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
@@ -94,9 +95,8 @@ static int usb_serial_device_remove (struct device *dev)
int minor;
port = to_usb_serial_port(dev);
- if (!port) {
+ if (!port)
return -ENODEV;
- }
device_remove_file(&port->dev, &dev_attr_port_number);
@@ -107,12 +107,12 @@ static int usb_serial_device_remove (struct device *dev)
retval = -EIO;
goto exit;
}
- retval = driver->port_remove (port);
+ retval = driver->port_remove(port);
module_put(driver->driver.owner);
}
exit:
minor = port->number;
- tty_unregister_device (usb_serial_tty_driver, minor);
+ tty_unregister_device(usb_serial_tty_driver, minor);
dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
driver->description, minor);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 1f7c86bd829..f61e3ca6430 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -232,7 +232,8 @@ error: kfree(priv);
}
/* open this device, set default parameters */
-static int ch341_open(struct usb_serial_port *port, struct file *filp)
+static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
@@ -256,7 +257,7 @@ static int ch341_open(struct usb_serial_port *port, struct file *filp)
if (r)
goto out;
- r = usb_serial_generic_open(port, filp);
+ r = usb_serial_generic_open(tty, port, filp);
out: return r;
}
@@ -264,11 +265,10 @@ out: return r;
/* Old_termios contains the original termios settings and
* tty->termios contains the new setting to be used.
*/
-static void ch341_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void ch341_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned baud_rate;
dbg("ch341_set_termios()");
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 201184c3fb8..7b74238ad1c 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -6,7 +6,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
- *
+ *
* Thanks to Randy Dunlap for the original version of this code.
*
*/
@@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options)
struct tty_struct *tty = NULL;
struct ktermios *termios = NULL, dummy;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
if (options) {
baud = simple_strtoul(options, NULL, 10);
@@ -81,55 +81,27 @@ static int usb_console_setup(struct console *co, char *options)
if (*s)
doflow = (*s++ == 'r');
}
+
+ /* Sane default */
+ if (baud == 0)
+ baud = 9600;
- /* build a cflag setting */
- switch (baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- case 9600:
- default:
- cflag |= B9600;
- /*
- * Set this to a sane value to prevent a divide error
- */
- baud = 9600;
- break;
- }
switch (bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- case 8:
- cflag |= CS8;
- break;
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ case 8:
+ cflag |= CS8;
+ break;
}
switch (parity) {
- case 'o': case 'O':
- cflag |= PARODD;
- break;
- case 'e': case 'E':
- cflag |= PARENB;
- break;
+ case 'o': case 'O':
+ cflag |= PARODD;
+ break;
+ case 'e': case 'E':
+ cflag |= PARENB;
+ break;
}
co->cflag = cflag;
@@ -140,17 +112,17 @@ static int usb_console_setup(struct console *co, char *options)
serial = usb_serial_get_by_index(co->index);
if (serial == NULL) {
/* no device is connected yet, sorry :( */
- err ("No USB device connected to ttyUSB%i", co->index);
+ err("No USB device connected to ttyUSB%i", co->index);
return -ENODEV;
}
port = serial->port[0];
- port->tty = NULL;
+ port->port.tty = NULL;
info->port = port;
-
- ++port->open_count;
- if (port->open_count == 1) {
+
+ ++port->port.count;
+ if (port->port.count == 1) {
if (serial->type->set_termios) {
/*
* allocate a fake tty so the driver can initialize
@@ -171,15 +143,15 @@ static int usb_console_setup(struct console *co, char *options)
}
memset(&dummy, 0, sizeof(struct ktermios));
tty->termios = termios;
- port->tty = tty;
+ port->port.tty = tty;
}
- /* only call the device specific open if this
+ /* only call the device specific open if this
* is the first time the port is opened */
if (serial->type->open)
- retval = serial->type->open(port, NULL);
+ retval = serial->type->open(NULL, port, NULL);
else
- retval = usb_serial_generic_open(port, NULL);
+ retval = usb_serial_generic_open(NULL, port, NULL);
if (retval) {
err("could not open USB console port");
@@ -188,9 +160,10 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) {
termios->c_cflag = cflag;
- serial->type->set_termios(port, &dummy);
+ tty_termios_encode_baud_rate(termios, baud, baud);
+ serial->type->set_termios(NULL, port, &dummy);
- port->tty = NULL;
+ port->port.tty = NULL;
kfree(termios);
kfree(tty);
}
@@ -203,15 +176,16 @@ out:
return retval;
free_termios:
kfree(termios);
- port->tty = NULL;
+ port->port.tty = NULL;
free_tty:
kfree(tty);
reset_open_count:
- port->open_count = 0;
+ port->port.count = 0;
goto out;
}
-static void usb_console_write(struct console *co, const char *buf, unsigned count)
+static void usb_console_write(struct console *co,
+ const char *buf, unsigned count)
{
static struct usbcons_info *info = &usbcons_info;
struct usb_serial_port *port = info->port;
@@ -227,8 +201,8 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- if (!port->open_count) {
- dbg ("%s - port not opened", __func__);
+ if (!port->port.count) {
+ dbg("%s - port not opened", __func__);
return;
}
@@ -236,26 +210,29 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
unsigned int i;
unsigned int lf;
/* search for LF so we can insert CR if necessary */
- for (i=0, lf=0 ; i < count ; i++) {
+ for (i = 0, lf = 0 ; i < count ; i++) {
if (*(buf + i) == 10) {
lf = 1;
i++;
break;
}
}
- /* pass on to the driver specific version of this function if it is available */
+ /* pass on to the driver specific version of this function if
+ it is available */
if (serial->type->write)
- retval = serial->type->write(port, buf, i);
+ retval = serial->type->write(NULL, port, buf, i);
else
- retval = usb_serial_generic_write(port, buf, i);
+ retval = usb_serial_generic_write(NULL, port, buf, i);
dbg("%s - return value : %d", __func__, retval);
if (lf) {
/* append CR after LF */
unsigned char cr = 13;
if (serial->type->write)
- retval = serial->type->write(port, &cr, 1);
+ retval = serial->type->write(NULL,
+ port, &cr, 1);
else
- retval = usb_serial_generic_write(port, &cr, 1);
+ retval = usb_serial_generic_write(NULL,
+ port, &cr, 1);
dbg("%s - return value : %d", __func__, retval);
}
buf += i;
@@ -273,18 +250,19 @@ static struct console usbcons = {
void usb_serial_console_disconnect(struct usb_serial *serial)
{
- if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) {
+ if (serial && serial->port && serial->port[0]
+ && serial->port[0] == usbcons_info.port) {
usb_serial_console_exit();
usb_serial_put(serial);
}
}
-void usb_serial_console_init (int serial_debug, int minor)
+void usb_serial_console_init(int serial_debug, int minor)
{
debug = serial_debug;
if (minor == 0) {
- /*
+ /*
* Call register_console() if this is the first device plugged
* in. If we call it earlier, then the callback to
* console_setup() will fail, as there is not a device seen by
@@ -293,21 +271,21 @@ void usb_serial_console_init (int serial_debug, int minor)
/*
* Register console.
* NOTES:
- * console_setup() is called (back) immediately (from register_console).
- * console_write() is called immediately from register_console iff
- * CON_PRINTBUFFER is set in flags.
+ * console_setup() is called (back) immediately (from
+ * register_console). console_write() is called immediately
+ * from register_console iff CON_PRINTBUFFER is set in flags.
*/
- dbg ("registering the USB serial console.");
+ dbg("registering the USB serial console.");
register_console(&usbcons);
}
}
-void usb_serial_console_exit (void)
+void usb_serial_console_exit(void)
{
if (usbcons_info.port) {
unregister_console(&usbcons);
- if (usbcons_info.port->open_count)
- usbcons_info.port->open_count--;
+ if (usbcons_info.port->port.count)
+ usbcons_info.port->port.count--;
usbcons_info.port = NULL;
}
}
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index f5b57b196c5..442cba69cce 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -25,7 +25,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb/serial.h>
/*
@@ -37,17 +37,20 @@
/*
* Function Prototypes
*/
-static int cp2101_open(struct usb_serial_port*, struct file*);
-static void cp2101_cleanup(struct usb_serial_port*);
-static void cp2101_close(struct usb_serial_port*, struct file*);
-static void cp2101_get_termios(struct usb_serial_port*);
-static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*);
-static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
-static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
+static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
+ struct file *);
+static void cp2101_cleanup(struct usb_serial_port *);
+static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
+ struct file*);
+static void cp2101_get_termios(struct tty_struct *);
+static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios*);
+static int cp2101_tiocmget(struct tty_struct *, struct file *);
+static int cp2101_tiocmset(struct tty_struct *, struct file *,
unsigned int, unsigned int);
-static void cp2101_break_ctl(struct usb_serial_port*, int);
-static int cp2101_startup (struct usb_serial *);
-static void cp2101_shutdown(struct usb_serial*);
+static void cp2101_break_ctl(struct tty_struct *, int);
+static int cp2101_startup(struct usb_serial *);
+static void cp2101_shutdown(struct usb_serial *);
static int debug;
@@ -93,7 +96,7 @@ static struct usb_device_id id_table [] = {
{ } /* Terminating Entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver cp2101_driver = {
.name = "cp2101",
@@ -182,7 +185,7 @@ static struct usb_serial_driver cp2101_device = {
* 'data' is a pointer to a pre-allocated array of integers large
* enough to hold 'size' bytes (with 4 bytes to each integer)
*/
-static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+static int cp2101_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
@@ -202,12 +205,12 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
request++;
/* Issue the request, attempting to read 'size' bytes */
- result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
0, buf, size, 300);
/* Convert data into an array of integers */
- for (i=0; i<length; i++)
+ for (i = 0; i < length; i++)
data[i] = le32_to_cpu(buf[i]);
kfree(buf);
@@ -228,7 +231,7 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
* Values less than 16 bits wide are sent directly
* 'size' is specified in bytes.
*/
-static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+static int cp2101_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
@@ -250,12 +253,12 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
buf[i] = cpu_to_le32(data[i]);
if (size > 2) {
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
0, buf, size, 300);
} else {
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
0, NULL, 0, 300);
@@ -271,7 +274,7 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
}
/* Single data value */
- result = usb_control_msg (serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
0, NULL, 0, 300);
@@ -283,13 +286,14 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
* Convenience function for calling cp2101_set_config on single data values
* without requiring an integer pointer
*/
-static inline int cp2101_set_config_single(struct usb_serial_port* port,
+static inline int cp2101_set_config_single(struct usb_serial_port *port,
u8 request, unsigned int data)
{
return cp2101_set_config(port, request, &data, 2);
}
-static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
int result;
@@ -303,7 +307,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
}
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -318,15 +322,15 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
}
/* Configure the termios structure */
- cp2101_get_termios(port);
+ cp2101_get_termios(tty);
/* Set the DTR and RTS pins low */
- cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+ cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0);
return 0;
}
-static void cp2101_cleanup (struct usb_serial_port *port)
+static void cp2101_cleanup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -341,7 +345,8 @@ static void cp2101_cleanup (struct usb_serial_port *port)
}
}
-static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -362,19 +367,15 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
* from the device, corrects any unsupported values, and configures the
* termios structure to reflect the state of the device
*/
-static void cp2101_get_termios (struct usb_serial_port *port)
+static void cp2101_get_termios (struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int cflag, modem_ctl[4];
- int baud;
- int bits;
+ unsigned int baud;
+ unsigned int bits;
dbg("%s - port %d", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty structures", __func__);
- return;
- }
-
cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
/* Convert to baudrate */
if (baud)
@@ -382,104 +383,102 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - baud rate = %d", __func__, baud);
- tty_encode_baud_rate(port->tty, baud, baud);
- cflag = port->tty->termios->c_cflag;
+ tty_encode_baud_rate(tty, baud, baud);
+ cflag = tty->termios->c_cflag;
cp2101_get_config(port, CP2101_BITS, &bits, 2);
cflag &= ~CSIZE;
- switch(bits & BITS_DATA_MASK) {
- case BITS_DATA_5:
- dbg("%s - data bits = 5", __func__);
- cflag |= CS5;
- break;
- case BITS_DATA_6:
- dbg("%s - data bits = 6", __func__);
- cflag |= CS6;
- break;
- case BITS_DATA_7:
- dbg("%s - data bits = 7", __func__);
- cflag |= CS7;
- break;
- case BITS_DATA_8:
- dbg("%s - data bits = 8", __func__);
- cflag |= CS8;
- break;
- case BITS_DATA_9:
- dbg("%s - data bits = 9 (not supported, "
- "using 8 data bits)", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- default:
- dbg("%s - Unknown number of data bits, "
- "using 8", __func__);
- cflag |= CS8;
- bits &= ~BITS_DATA_MASK;
- bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_DATA_MASK) {
+ case BITS_DATA_5:
+ dbg("%s - data bits = 5", __func__);
+ cflag |= CS5;
+ break;
+ case BITS_DATA_6:
+ dbg("%s - data bits = 6", __func__);
+ cflag |= CS6;
+ break;
+ case BITS_DATA_7:
+ dbg("%s - data bits = 7", __func__);
+ cflag |= CS7;
+ break;
+ case BITS_DATA_8:
+ dbg("%s - data bits = 8", __func__);
+ cflag |= CS8;
+ break;
+ case BITS_DATA_9:
+ dbg("%s - data bits = 9 (not supported, using 8 data bits)",
+ __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ default:
+ dbg("%s - Unknown number of data bits, using 8", __func__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
- switch(bits & BITS_PARITY_MASK) {
- case BITS_PARITY_NONE:
- dbg("%s - parity = NONE", __func__);
- cflag &= ~PARENB;
- break;
- case BITS_PARITY_ODD:
- dbg("%s - parity = ODD", __func__);
- cflag |= (PARENB|PARODD);
- break;
- case BITS_PARITY_EVEN:
- dbg("%s - parity = EVEN", __func__);
- cflag &= ~PARODD;
- cflag |= PARENB;
- break;
- case BITS_PARITY_MARK:
- dbg("%s - parity = MARK (not supported, "
- "disabling parity)", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- case BITS_PARITY_SPACE:
- dbg("%s - parity = SPACE (not supported, "
- "disabling parity)", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- default:
- dbg("%s - Unknown parity mode, "
- "disabling parity", __func__);
- cflag &= ~PARENB;
- bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_PARITY_MASK) {
+ case BITS_PARITY_NONE:
+ dbg("%s - parity = NONE", __func__);
+ cflag &= ~PARENB;
+ break;
+ case BITS_PARITY_ODD:
+ dbg("%s - parity = ODD", __func__);
+ cflag |= (PARENB|PARODD);
+ break;
+ case BITS_PARITY_EVEN:
+ dbg("%s - parity = EVEN", __func__);
+ cflag &= ~PARODD;
+ cflag |= PARENB;
+ break;
+ case BITS_PARITY_MARK:
+ dbg("%s - parity = MARK (not supported, disabling parity)",
+ __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_PARITY_SPACE:
+ dbg("%s - parity = SPACE (not supported, disabling parity)",
+ __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ default:
+ dbg("%s - Unknown parity mode, disabling parity", __func__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
cflag &= ~CSTOPB;
- switch(bits & BITS_STOP_MASK) {
- case BITS_STOP_1:
- dbg("%s - stop bits = 1", __func__);
- break;
- case BITS_STOP_1_5:
- dbg("%s - stop bits = 1.5 (not supported, "
- "using 1 stop bit)", __func__);
- bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
- case BITS_STOP_2:
- dbg("%s - stop bits = 2", __func__);
- cflag |= CSTOPB;
- break;
- default:
- dbg("%s - Unknown number of stop bits, "
- "using 1 stop bit", __func__);
- bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, &bits, 2);
- break;
+ switch (bits & BITS_STOP_MASK) {
+ case BITS_STOP_1:
+ dbg("%s - stop bits = 1", __func__);
+ break;
+ case BITS_STOP_1_5:
+ dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)",
+ __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
+ case BITS_STOP_2:
+ dbg("%s - stop bits = 2", __func__);
+ cflag |= CSTOPB;
+ break;
+ default:
+ dbg("%s - Unknown number of stop bits, using 1 stop bit",
+ __func__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
+ break;
}
cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
@@ -491,55 +490,53 @@ static void cp2101_get_termios (struct usb_serial_port *port)
cflag &= ~CRTSCTS;
}
- port->tty->termios->c_cflag = cflag;
+ tty->termios->c_cflag = cflag;
}
-static void cp2101_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void cp2101_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
- int baud=0, bits;
+ unsigned int baud = 0, bits;
unsigned int modem_ctl[4];
dbg("%s - port %d", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty structures", __func__);
+ if (!tty)
return;
- }
- port->tty->termios->c_cflag &= ~CMSPAR;
- cflag = port->tty->termios->c_cflag;
+ tty->termios->c_cflag &= ~CMSPAR;
+ cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
/* If the baud rate is to be updated*/
if (baud != tty_termios_baud_rate(old_termios)) {
switch (baud) {
- case 0:
- case 600:
- case 1200:
- case 1800:
- case 2400:
- case 4800:
- case 7200:
- case 9600:
- case 14400:
- case 19200:
- case 28800:
- case 38400:
- case 55854:
- case 57600:
- case 115200:
- case 127117:
- case 230400:
- case 460800:
- case 921600:
- case 3686400:
- break;
- default:
- baud = 9600;
- break;
+ case 0:
+ case 600:
+ case 1200:
+ case 1800:
+ case 2400:
+ case 4800:
+ case 7200:
+ case 9600:
+ case 14400:
+ case 19200:
+ case 28800:
+ case 38400:
+ case 55854:
+ case 57600:
+ case 115200:
+ case 127117:
+ case 230400:
+ case 460800:
+ case 921600:
+ case 3686400:
+ break;
+ default:
+ baud = 9600;
+ break;
}
if (baud) {
@@ -554,35 +551,35 @@ static void cp2101_set_termios (struct usb_serial_port *port,
}
}
/* Report back the resulting baud rate */
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
cp2101_get_config(port, CP2101_BITS, &bits, 2);
bits &= ~BITS_DATA_MASK;
switch (cflag & CSIZE) {
- case CS5:
- bits |= BITS_DATA_5;
- dbg("%s - data bits = 5", __func__);
- break;
- case CS6:
- bits |= BITS_DATA_6;
- dbg("%s - data bits = 6", __func__);
- break;
- case CS7:
- bits |= BITS_DATA_7;
- dbg("%s - data bits = 7", __func__);
- break;
- case CS8:
- bits |= BITS_DATA_8;
- dbg("%s - data bits = 8", __func__);
- break;
- /*case CS9:
- bits |= BITS_DATA_9;
- dbg("%s - data bits = 9", __func__);
- break;*/
- default:
- dev_err(&port->dev, "cp2101 driver does not "
+ case CS5:
+ bits |= BITS_DATA_5;
+ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ bits |= BITS_DATA_6;
+ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ bits |= BITS_DATA_7;
+ dbg("%s - data bits = 7", __func__);
+ break;
+ case CS8:
+ bits |= BITS_DATA_8;
+ dbg("%s - data bits = 8", __func__);
+ break;
+ /*case CS9:
+ bits |= BITS_DATA_9;
+ dbg("%s - data bits = 9", __func__);
+ break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
"support the number of bits requested,"
" using 8 bit mode\n");
bits |= BITS_DATA_8;
@@ -651,10 +648,11 @@ static void cp2101_set_termios (struct usb_serial_port *port,
}
-static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cp2101_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- int control = 0;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int control = 0;
dbg("%s - port %d", __func__, port->number);
@@ -681,9 +679,11 @@ static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
}
-static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cp2101_tiocmget (struct tty_struct *tty, struct file *file)
{
- int control, result;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int control;
+ int result;
dbg("%s - port %d", __func__, port->number);
@@ -701,9 +701,10 @@ static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
return result;
}
-static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+static void cp2101_break_ctl (struct tty_struct *tty, int break_state)
{
- int state;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int state;
dbg("%s - port %d", __func__, port->number);
if (break_state == 0)
@@ -711,30 +712,29 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
else
state = BREAK_ON;
dbg("%s - turning break %s", __func__,
- state==BREAK_OFF ? "off" : "on");
+ state == BREAK_OFF ? "off" : "on");
cp2101_set_config(port, CP2101_BREAK, &state, 2);
}
-static int cp2101_startup (struct usb_serial *serial)
+static int cp2101_startup(struct usb_serial *serial)
{
/* CP2101 buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
return 0;
}
-static void cp2101_shutdown (struct usb_serial *serial)
+static void cp2101_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s", __func__);
/* Stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
cp2101_cleanup(serial->port[i]);
- }
}
-static int __init cp2101_init (void)
+static int __init cp2101_init(void)
{
int retval;
@@ -754,10 +754,10 @@ static int __init cp2101_init (void)
return 0;
}
-static void __exit cp2101_exit (void)
+static void __exit cp2101_exit(void)
{
- usb_deregister (&cp2101_driver);
- usb_serial_deregister (&cp2101_device);
+ usb_deregister(&cp2101_driver);
+ usb_serial_deregister(&cp2101_device);
}
module_init(cp2101_init);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index c164e2cf275..b4d72351cb9 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -37,7 +37,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -57,22 +57,25 @@ static int debug;
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static int cyberjack_startup (struct usb_serial *serial);
-static void cyberjack_shutdown (struct usb_serial *serial);
-static int cyberjack_open (struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int cyberjack_write_room( struct usb_serial_port *port );
-static void cyberjack_read_int_callback (struct urb *urb);
-static void cyberjack_read_bulk_callback (struct urb *urb);
-static void cyberjack_write_bulk_callback (struct urb *urb);
+static int cyberjack_startup(struct usb_serial *serial);
+static void cyberjack_shutdown(struct usb_serial *serial);
+static int cyberjack_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int cyberjack_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count);
+static int cyberjack_write_room(struct tty_struct *tty);
+static void cyberjack_read_int_callback(struct urb *urb);
+static void cyberjack_read_bulk_callback(struct urb *urb);
+static void cyberjack_write_bulk_callback(struct urb *urb);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver cyberjack_driver = {
.name = "cyberjack",
@@ -111,7 +114,7 @@ struct cyberjack_private {
};
/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup (struct usb_serial *serial)
+static int cyberjack_startup(struct usb_serial *serial)
{
struct cyberjack_private *priv;
int i;
@@ -135,20 +138,20 @@ static int cyberjack_startup (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
int result;
serial->port[i]->interrupt_in_urb->dev = serial->dev;
- result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
+ result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
GFP_KERNEL);
if (result)
err(" usb_submit_urb(read int) failed");
dbg("%s - usb_submit_urb(int urb)", __func__);
}
- return( 0 );
+ return 0;
}
-static void cyberjack_shutdown (struct usb_serial *serial)
+static void cyberjack_shutdown(struct usb_serial *serial)
{
int i;
-
+
dbg("%s", __func__);
for (i = 0; i < serial->num_ports; ++i) {
@@ -158,8 +161,9 @@ static void cyberjack_shutdown (struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], NULL);
}
}
-
-static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
+
+static int cyberjack_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cyberjack_private *priv;
unsigned long flags;
@@ -167,14 +171,15 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
- dbg("%s - usb_clear_halt", __func__ );
+ dbg("%s - usb_clear_halt", __func__);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
/* force low_latency on so that our tty_push actually forces
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
@@ -186,7 +191,8 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
return result;
}
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -197,7 +203,8 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
}
}
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cyberjack_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -223,7 +230,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
spin_lock_irqsave(&priv->lock, flags);
- if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
+ if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
/* To much data for buffer. Reset buffer. */
priv->wrfilled = 0;
port->write_urb_busy = 0;
@@ -232,42 +239,43 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
}
/* Copy data */
- memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+ memcpy(priv->wrbuf + priv->wrfilled, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count,
- priv->wrbuf+priv->wrfilled);
+ priv->wrbuf + priv->wrfilled);
priv->wrfilled += count;
- if( priv->wrfilled >= 3 ) {
+ if (priv->wrfilled >= 3) {
wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
dbg("%s - expected data: %d", __func__, wrexpected);
- } else {
+ } else
wrexpected = sizeof(priv->wrbuf);
- }
- if( priv->wrfilled >= wrexpected ) {
+ if (priv->wrfilled >= wrexpected) {
/* We have enough data to begin transmission */
int length;
dbg("%s - transmitting data (frame 1)", __func__);
- length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
+ length = (wrexpected > port->bulk_out_size) ?
+ port->bulk_out_size : wrexpected;
- memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
- priv->wrsent=length;
+ memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length);
+ priv->wrsent = length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, length,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ cyberjack_write_bulk_callback),
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -276,12 +284,12 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
return 0;
}
- dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+ dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
- if( priv->wrsent>=priv->wrfilled ) {
+ if (priv->wrsent >= priv->wrfilled) {
dbg("%s - buffer cleaned", __func__);
- memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+ memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
}
@@ -289,16 +297,16 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
spin_unlock_irqrestore(&priv->lock, flags);
- return (count);
-}
+ return count;
+}
-static int cyberjack_write_room( struct usb_serial_port *port )
+static int cyberjack_write_room(struct tty_struct *tty)
{
/* FIXME: .... */
return CYBERJACK_LOCAL_BUF_SIZE;
}
-static void cyberjack_read_int_callback( struct urb *urb )
+static void cyberjack_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -312,10 +320,11 @@ static void cyberjack_read_int_callback( struct urb *urb )
if (status)
return;
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* React only to interrupts signaling a bulk_in transfer */
- if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
+ if (urb->actual_length == 4 && data[0] == 0x01) {
short old_rdtodo;
/* This is a announcement of coming bulk_ins. */
@@ -325,8 +334,8 @@ static void cyberjack_read_int_callback( struct urb *urb )
old_rdtodo = priv->rdtodo;
- if( (old_rdtodo+size)<(old_rdtodo) ) {
- dbg( "To many bulk_in urbs to do." );
+ if (old_rdtodo + size < old_rdtodo) {
+ dbg("To many bulk_in urbs to do.");
spin_unlock(&priv->lock);
goto resubmit;
}
@@ -338,10 +347,10 @@ static void cyberjack_read_int_callback( struct urb *urb )
spin_unlock(&priv->lock);
- if( !old_rdtodo ) {
+ if (!old_rdtodo) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if( result )
+ if (result)
err("%s - failed resubmitting read urb, error %d", __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
@@ -355,7 +364,7 @@ resubmit:
dbg("%s - usb_submit_urb(int urb)", __func__);
}
-static void cyberjack_read_bulk_callback (struct urb *urb)
+static void cyberjack_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -367,14 +376,15 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
if (status) {
dbg("%s - nonzero read bulk status received: %d",
__func__, status);
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
dbg("%s - ignoring since device not open\n", __func__);
return;
@@ -382,15 +392,16 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ tty_flip_buffer_push(tty);
}
spin_lock(&priv->lock);
/* Reduce urbs to do by one. */
- priv->rdtodo-=urb->actual_length;
+ priv->rdtodo -= urb->actual_length;
/* Just to be sure */
- if ( priv->rdtodo<0 ) priv->rdtodo = 0;
+ if (priv->rdtodo < 0)
+ priv->rdtodo = 0;
todo = priv->rdtodo;
spin_unlock(&priv->lock);
@@ -398,16 +409,17 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
dbg("%s - rdtodo: %d", __func__, todo);
/* Continue to read if we have still urbs to do. */
- if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
+ if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
dbg("%s - usb_submit_urb(read urb)", __func__);
}
}
-static void cyberjack_write_bulk_callback (struct urb *urb)
+static void cyberjack_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -425,7 +437,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
spin_lock(&priv->lock);
/* only do something if we have more data to send */
- if( priv->wrfilled ) {
+ if (priv->wrfilled) {
int length, blksize, result;
dbg("%s - transmitting data (frame n)", __func__);
@@ -433,37 +445,39 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
port->bulk_out_size : (priv->wrfilled - priv->wrsent);
- memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent,
- length );
- priv->wrsent+=length;
+ memcpy(port->write_urb->transfer_buffer,
+ priv->wrbuf + priv->wrsent, length);
+ priv->wrsent += length;
/* set up our urb */
- usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, length,
- ((port->serial->type->write_bulk_callback) ?
- port->serial->type->write_bulk_callback :
- cyberjack_write_bulk_callback),
+ ((port->serial->type->write_bulk_callback) ?
+ port->serial->type->write_bulk_callback :
+ cyberjack_write_bulk_callback),
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
/* Throw away data. No better idea what to do with it. */
priv->wrfilled = 0;
priv->wrsent = 0;
goto exit;
}
- dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
- dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+ dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+ dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
- if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
+ if (priv->wrsent >= priv->wrfilled ||
+ priv->wrsent >= blksize) {
dbg("%s - buffer cleaned", __func__);
- memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+ memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
priv->wrfilled = 0;
priv->wrsent = 0;
}
@@ -474,14 +488,14 @@ exit:
usb_serial_port_softint(port);
}
-static int __init cyberjack_init (void)
+static int __init cyberjack_init(void)
{
int retval;
retval = usb_serial_register(&cyberjack_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&cyberjack_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -494,18 +508,18 @@ failed_usb_serial_register:
return retval;
}
-static void __exit cyberjack_exit (void)
+static void __exit cyberjack_exit(void)
{
- usb_deregister (&cyberjack_driver);
- usb_serial_deregister (&cyberjack_device);
+ usb_deregister(&cyberjack_driver);
+ usb_serial_deregister(&cyberjack_device);
}
module_init(cyberjack_init);
module_exit(cyberjack_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 0230d3c0888..22837a3f2f8 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -2,7 +2,7 @@
* USB Cypress M8 driver
*
* Copyright (C) 2004
- * Lonnie Mendez (dignome@gmail.com)
+ * Lonnie Mendez (dignome@gmail.com)
* Copyright (C) 2003,2004
* Neil Whelchel (koyama@firstlight.net)
*
@@ -11,19 +11,21 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* See http://geocities.com/i0xox0i for information on this driver and the
* earthmate usb device.
*
* Lonnie Mendez <dignome@gmail.com>
* 4-29-2005
- * Fixed problem where setting or retreiving the serial config would fail with
- * EPIPE. Removed CRTS toggling so the driver behaves more like other usbserial
- * adapters. Issued new interval of 1ms instead of the default 10ms. As a
- * result, transfer speed has been substantially increased. From avg. 850bps to
- * avg. 3300bps. initial termios has also been modified. Cleaned up code and
- * formatting issues so it is more readable. Replaced the C++ style comments.
+ * Fixed problem where setting or retreiving the serial config would fail
+ * with EPIPE. Removed CRTS toggling so the driver behaves more like
+ * other usbserial adapters. Issued new interval of 1ms instead of the
+ * default 10ms. As a result, transfer speed has been substantially
+ * increased from avg. 850bps to avg. 3300bps. initial termios has also
+ * been modified. Cleaned up code and formatting issues so it is more
+ * readable. Replaced the C++ style comments.
*
* Lonnie Mendez <dignome@gmail.com>
* 12-15-2004
@@ -42,10 +44,11 @@
*
*/
-/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */
+/* Thanks to Neil Whelchel for writing the first cypress m8 implementation
+ for linux. */
/* Thanks to cypress for providing references for the hid reports. */
/* Thanks to Jiang Zhang for providing links and for general help. */
-/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */
+/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
#include <linux/kernel.h>
@@ -62,7 +65,7 @@
#include <linux/usb/serial.h>
#include <linux/serial.h>
#include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "cypress_m8.h"
@@ -112,7 +115,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver cypress_driver = {
.name = "cypress",
@@ -146,11 +149,13 @@ struct cypress_private {
__u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */
enum packet_format pkt_fmt; /* format to use for packet send / receive */
int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */
- int baud_rate; /* stores current baud rate in integer form */
+ int baud_rate; /* stores current baud rate in
+ integer form */
int isthrottled; /* if throttled, discard reads */
wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
- /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
+ /* we pass a pointer to this as the arguement sent to
+ cypress_set_termios old_termios */
struct ktermios tmp_termios; /* stores the old termios settings */
};
@@ -163,33 +168,41 @@ struct cypress_buf {
};
/* function prototypes for the Cypress USB to serial device */
-static int cypress_earthmate_startup (struct usb_serial *serial);
-static int cypress_hidcom_startup (struct usb_serial *serial);
-static int cypress_ca42v2_startup (struct usb_serial *serial);
-static void cypress_shutdown (struct usb_serial *serial);
-static int cypress_open (struct usb_serial_port *port, struct file *filp);
-static void cypress_close (struct usb_serial_port *port, struct file *filp);
-static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static void cypress_send (struct usb_serial_port *port);
-static int cypress_write_room (struct usb_serial_port *port);
-static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int cypress_tiocmget (struct usb_serial_port *port, struct file *file);
-static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int cypress_chars_in_buffer (struct usb_serial_port *port);
-static void cypress_throttle (struct usb_serial_port *port);
-static void cypress_unthrottle (struct usb_serial_port *port);
-static void cypress_set_dead (struct usb_serial_port *port);
-static void cypress_read_int_callback (struct urb *urb);
-static void cypress_write_int_callback (struct urb *urb);
+static int cypress_earthmate_startup(struct usb_serial *serial);
+static int cypress_hidcom_startup(struct usb_serial *serial);
+static int cypress_ca42v2_startup(struct usb_serial *serial);
+static void cypress_shutdown(struct usb_serial *serial);
+static int cypress_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static void cypress_send(struct usb_serial_port *port);
+static int cypress_write_room(struct tty_struct *tty);
+static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void cypress_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int cypress_tiocmget(struct tty_struct *tty, struct file *file);
+static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int cypress_chars_in_buffer(struct tty_struct *tty);
+static void cypress_throttle(struct tty_struct *tty);
+static void cypress_unthrottle(struct tty_struct *tty);
+static void cypress_set_dead(struct usb_serial_port *port);
+static void cypress_read_int_callback(struct urb *urb);
+static void cypress_write_int_callback(struct urb *urb);
/* write buffer functions */
static struct cypress_buf *cypress_buf_alloc(unsigned int size);
-static void cypress_buf_free(struct cypress_buf *cb);
-static void cypress_buf_clear(struct cypress_buf *cb);
-static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
-static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
-static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count);
-static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
+static void cypress_buf_free(struct cypress_buf *cb);
+static void cypress_buf_clear(struct cypress_buf *cb);
+static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_put(struct cypress_buf *cb,
+ const char *buf, unsigned int count);
+static unsigned int cypress_buf_get(struct cypress_buf *cb,
+ char *buf, unsigned int count);
static struct usb_serial_driver cypress_earthmate_device = {
@@ -247,7 +260,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
static struct usb_serial_driver cypress_ca42v2_device = {
.driver = {
.owner = THIS_MODULE,
- .name = "nokiaca42v2",
+ .name = "nokiaca42v2",
},
.description = "Nokia CA-42 V2 Adapter",
.usb_driver = &cypress_driver,
@@ -322,8 +335,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate)
/* This function can either set or retrieve the current serial line settings */
-static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
- int parity_enable, int parity_type, int reset, int cypress_request_type)
+static int cypress_serial_control(struct tty_struct *tty,
+ struct usb_serial_port *port, speed_t baud_rate, int data_bits,
+ int stop_bits, int parity_enable, int parity_type, int reset,
+ int cypress_request_type)
{
int new_baudrate = 0, retval = 0, tries = 0;
struct cypress_private *priv;
@@ -331,111 +346,114 @@ static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_ra
unsigned long flags;
dbg("%s", __func__);
-
+
priv = usb_get_serial_port_data(port);
if (!priv->comm_is_ok)
return -ENODEV;
- switch(cypress_request_type) {
- case CYPRESS_SET_CONFIG:
+ switch (cypress_request_type) {
+ case CYPRESS_SET_CONFIG:
+ new_baudrate = priv->baud_rate;
+ /* 0 means 'Hang up' so doesn't change the true bit rate */
+ if (baud_rate == 0)
new_baudrate = priv->baud_rate;
- /* 0 means 'Hang up' so doesn't change the true bit rate */
- if (baud_rate == 0)
- new_baudrate = priv->baud_rate;
- /* Change of speed ? */
- else if (baud_rate != priv->baud_rate) {
- dbg("%s - baud rate is changing", __func__);
- retval = analyze_baud_rate(port, baud_rate);
- if (retval >= 0) {
- new_baudrate = retval;
- dbg("%s - New baud rate set to %d",
- __func__, new_baudrate);
- }
- }
- dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
-
- memset(feature_buffer, 0, sizeof(feature_buffer));
- /* fill the feature_buffer with new configuration */
- *((u_int32_t *)feature_buffer) = new_baudrate;
-
- feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
- /* 1 bit gap */
- feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
- feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */
- feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */
- /* 1 bit gap */
- feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
-
- dbg("%s - device is being sent this feature report:", __func__);
- dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
- feature_buffer[2], feature_buffer[3], feature_buffer[4]);
-
- do {
- retval = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- HID_REQ_SET_REPORT,
- USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
- 0x0300, 0, feature_buffer,
- sizeof(feature_buffer), 500);
-
- if (tries++ >= 3)
- break;
-
- } while (retval != sizeof(feature_buffer) &&
- retval != -ENODEV);
-
- if (retval != sizeof(feature_buffer)) {
- err("%s - failed sending serial line settings - %d", __func__, retval);
- cypress_set_dead(port);
- } else {
- spin_lock_irqsave(&priv->lock, flags);
- priv->baud_rate = new_baudrate;
- priv->current_config = feature_buffer[4];
- spin_unlock_irqrestore(&priv->lock, flags);
- /* If we asked for a speed change encode it */
- if (baud_rate)
- tty_encode_baud_rate(port->tty,
- new_baudrate, new_baudrate);
- }
- break;
- case CYPRESS_GET_CONFIG:
- if (priv->get_cfg_unsafe) {
- /* Not implemented for this device,
- and if we try to do it we're likely
- to crash the hardware. */
- return -ENOTTY;
- }
- dbg("%s - retreiving serial line settings", __func__);
- /* set initial values in feature buffer */
- memset(feature_buffer, 0, sizeof(feature_buffer));
-
- do {
- retval = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- HID_REQ_GET_REPORT,
- USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
- 0x0300, 0, feature_buffer,
- sizeof(feature_buffer), 500);
-
- if (tries++ >= 3)
- break;
-
- } while (retval != sizeof(feature_buffer) &&
- retval != -ENODEV);
-
- if (retval != sizeof(feature_buffer)) {
- err("%s - failed to retrieve serial line settings - %d", __func__, retval);
- cypress_set_dead(port);
- return retval;
- } else {
- spin_lock_irqsave(&priv->lock, flags);
-
- /* store the config in one byte, and later use bit masks to check values */
- priv->current_config = feature_buffer[4];
- priv->baud_rate = *((u_int32_t *)feature_buffer);
- spin_unlock_irqrestore(&priv->lock, flags);
+ /* Change of speed ? */
+ else if (baud_rate != priv->baud_rate) {
+ dbg("%s - baud rate is changing", __func__);
+ retval = analyze_baud_rate(port, baud_rate);
+ if (retval >= 0) {
+ new_baudrate = retval;
+ dbg("%s - New baud rate set to %d",
+ __func__, new_baudrate);
}
+ }
+ dbg("%s - baud rate is being sent as %d",
+ __func__, new_baudrate);
+
+ memset(feature_buffer, 0, sizeof(feature_buffer));
+ /* fill the feature_buffer with new configuration */
+ *((u_int32_t *)feature_buffer) = new_baudrate;
+ feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */
+ /* 1 bit gap */
+ feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */
+ feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */
+ feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */
+ /* 1 bit gap */
+ feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */
+
+ dbg("%s - device is being sent this feature report:",
+ __func__);
+ dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__,
+ feature_buffer[0], feature_buffer[1],
+ feature_buffer[2], feature_buffer[3],
+ feature_buffer[4]);
+
+ do {
+ retval = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ HID_REQ_SET_REPORT,
+ USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+ 0x0300, 0, feature_buffer,
+ sizeof(feature_buffer), 500);
+
+ if (tries++ >= 3)
+ break;
+
+ } while (retval != sizeof(feature_buffer) &&
+ retval != -ENODEV);
+
+ if (retval != sizeof(feature_buffer)) {
+ err("%s - failed sending serial line settings - %d",
+ __func__, retval);
+ cypress_set_dead(port);
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->baud_rate = new_baudrate;
+ priv->current_config = feature_buffer[4];
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /* If we asked for a speed change encode it */
+ if (baud_rate)
+ tty_encode_baud_rate(tty,
+ new_baudrate, new_baudrate);
+ }
+ break;
+ case CYPRESS_GET_CONFIG:
+ if (priv->get_cfg_unsafe) {
+ /* Not implemented for this device,
+ and if we try to do it we're likely
+ to crash the hardware. */
+ return -ENOTTY;
+ }
+ dbg("%s - retreiving serial line settings", __func__);
+ /* set initial values in feature buffer */
+ memset(feature_buffer, 0, sizeof(feature_buffer));
+
+ do {
+ retval = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+ 0x0300, 0, feature_buffer,
+ sizeof(feature_buffer), 500);
+
+ if (tries++ >= 3)
+ break;
+ } while (retval != sizeof(feature_buffer)
+ && retval != -ENODEV);
+
+ if (retval != sizeof(feature_buffer)) {
+ err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+ cypress_set_dead(port);
+ return retval;
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+ /* store the config in one byte, and later
+ use bit masks to check values */
+ priv->current_config = feature_buffer[4];
+ priv->baud_rate = *((u_int32_t *)feature_buffer);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
}
spin_lock_irqsave(&priv->lock, flags);
++priv->cmd_count;
@@ -468,14 +486,14 @@ static void cypress_set_dead(struct usb_serial_port *port)
*****************************************************************************/
-static int generic_startup (struct usb_serial *serial)
+static int generic_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
dbg("%s - port %d", __func__, port->number);
- priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -487,9 +505,9 @@ static int generic_startup (struct usb_serial *serial)
return -ENOMEM;
}
init_waitqueue_head(&priv->delta_msr_wait);
-
- usb_reset_configuration (serial->dev);
-
+
+ usb_reset_configuration(serial->dev);
+
priv->cmd_ctrl = 0;
priv->line_control = 0;
priv->termios_initialized = 0;
@@ -500,30 +518,30 @@ static int generic_startup (struct usb_serial *serial)
small. Otherwise we can use the slightly more compact
format. This is in accordance with the cypress_m8 serial
converter app note. */
- if (port->interrupt_out_size > 9) {
+ if (port->interrupt_out_size > 9)
priv->pkt_fmt = packet_format_1;
- } else {
+ else
priv->pkt_fmt = packet_format_2;
- }
+
if (interval > 0) {
priv->write_urb_interval = interval;
priv->read_urb_interval = interval;
dbg("%s - port %d read & write intervals forced to %d",
- __func__,port->number,interval);
+ __func__, port->number, interval);
} else {
priv->write_urb_interval = port->interrupt_out_urb->interval;
priv->read_urb_interval = port->interrupt_in_urb->interval;
dbg("%s - port %d intervals: read=%d write=%d",
- __func__,port->number,
- priv->read_urb_interval,priv->write_urb_interval);
+ __func__, port->number,
+ priv->read_urb_interval, priv->write_urb_interval);
}
usb_set_serial_port_data(port, priv);
-
+
return 0;
}
-static int cypress_earthmate_startup (struct usb_serial *serial)
+static int cypress_earthmate_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
@@ -541,7 +559,8 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
/* All Earthmate devices use the separated-count packet
format! Idiotic. */
priv->pkt_fmt = packet_format_1;
- if (serial->dev->descriptor.idProduct != cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
+ if (serial->dev->descriptor.idProduct !=
+ cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
/* The old original USB Earthmate seemed able to
handle GET_CONFIG requests; everything they've
produced since that time crashes if this command is
@@ -555,7 +574,7 @@ static int cypress_earthmate_startup (struct usb_serial *serial)
} /* cypress_earthmate_startup */
-static int cypress_hidcom_startup (struct usb_serial *serial)
+static int cypress_hidcom_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
@@ -569,12 +588,12 @@ static int cypress_hidcom_startup (struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
priv->chiptype = CT_CYPHIDCOM;
-
+
return 0;
} /* cypress_hidcom_startup */
-static int cypress_ca42v2_startup (struct usb_serial *serial)
+static int cypress_ca42v2_startup(struct usb_serial *serial)
{
struct cypress_private *priv;
@@ -593,11 +612,11 @@ static int cypress_ca42v2_startup (struct usb_serial *serial)
} /* cypress_ca42v2_startup */
-static void cypress_shutdown (struct usb_serial *serial)
+static void cypress_shutdown(struct usb_serial *serial)
{
struct cypress_private *priv;
- dbg ("%s - port %d", __func__, serial->port[0]->number);
+ dbg("%s - port %d", __func__, serial->port[0]->number);
/* all open ports are closed at this point */
@@ -611,7 +630,8 @@ static void cypress_shutdown (struct usb_serial *serial)
}
-static int cypress_open (struct usb_serial_port *port, struct file *filp)
+static int cypress_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -636,37 +656,44 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&priv->lock, flags);
/* setting to zero could cause data loss */
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* raise both lines and set termios */
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = CONTROL_DTR | CONTROL_RTS;
priv->cmd_ctrl = 1;
spin_unlock_irqrestore(&priv->lock, flags);
- result = cypress_write(port, NULL, 0);
+ result = cypress_write(tty, port, NULL, 0);
if (result) {
- dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed setting the control lines - error %d\n",
+ __func__, result);
return result;
} else
dbg("%s - success setting the control lines", __func__);
- cypress_set_termios(port, &priv->tmp_termios);
+ if (tty)
+ cypress_set_termios(tty, port, &priv->tmp_termios);
/* setup the port and start reading from the device */
- if(!port->interrupt_in_urb){
+ if (!port->interrupt_in_urb) {
err("%s - interrupt_in_urb is empty!", __func__);
- return(-1);
+ return -1;
}
usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
- port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
+ port->interrupt_in_urb->transfer_buffer,
+ port->interrupt_in_urb->transfer_buffer_length,
cypress_read_int_callback, port, priv->read_urb_interval);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
- if (result){
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ if (result) {
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
cypress_set_dead(port);
}
@@ -674,7 +701,8 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
} /* cypress_open */
-static void cypress_close(struct usb_serial_port *port, struct file * filp)
+static void cypress_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned int c_cflag;
@@ -688,7 +716,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
spin_lock_irq(&priv->lock);
timeout = CYPRESS_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (cypress_buf_data_avail(priv->buf) == 0
@@ -701,7 +729,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
spin_lock_irq(&priv->lock);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
cypress_buf_clear(priv->buf);
spin_unlock_irq(&priv->lock);
@@ -713,19 +741,21 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
return;
}
/* wait for characters to drain from device */
- bps = tty_get_baud_rate(port->tty);
- if (bps > 1200)
- timeout = max((HZ*2560)/bps,HZ/10);
- else
- timeout = 2*HZ;
- schedule_timeout_interruptible(timeout);
+ if (tty) {
+ bps = tty_get_baud_rate(tty);
+ if (bps > 1200)
+ timeout = max((HZ * 2560) / bps, HZ / 10);
+ else
+ timeout = 2 * HZ;
+ schedule_timeout_interruptible(timeout);
+ }
dbg("%s - stopping urbs", __func__);
- usb_kill_urb (port->interrupt_in_urb);
- usb_kill_urb (port->interrupt_out_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_out_urb);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop dtr and rts */
priv = usb_get_serial_port_data(port);
@@ -733,22 +763,23 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
priv->line_control = 0;
priv->cmd_ctrl = 1;
spin_unlock_irq(&priv->lock);
- cypress_write(port, NULL, 0);
+ cypress_write(tty, port, NULL, 0);
}
}
if (stats)
- dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
- priv->bytes_in, priv->bytes_out, priv->cmd_count);
+ dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
+ priv->bytes_in, priv->bytes_out, priv->cmd_count);
mutex_unlock(&port->serial->disc_mutex);
} /* cypress_close */
-static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
dbg("%s - port %d, %d bytes", __func__, port->number, count);
/* line control commands, which need to be executed immediately,
@@ -758,10 +789,10 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf,
count = 0;
goto finish;
}
-
+
if (!count)
return count;
-
+
spin_lock_irqsave(&priv->lock, flags);
count = cypress_buf_put(priv->buf, buf, count);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -778,13 +809,14 @@ static void cypress_send(struct usb_serial_port *port)
int count = 0, result, offset, actual_size;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
if (!priv->comm_is_ok)
return;
dbg("%s - port %d", __func__, port->number);
- dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
-
+ dbg("%s - interrupt out size is %d", __func__,
+ port->interrupt_out_size);
+
spin_lock_irqsave(&priv->lock, flags);
if (priv->write_urb_in_use) {
dbg("%s - can't write, urb in use", __func__);
@@ -794,7 +826,8 @@ static void cypress_send(struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->lock, flags);
/* clear buffer */
- memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
+ memset(port->interrupt_out_urb->transfer_buffer, 0,
+ port->interrupt_out_size);
spin_lock_irqsave(&priv->lock, flags);
switch (priv->pkt_fmt) {
@@ -825,9 +858,8 @@ static void cypress_send(struct usb_serial_port *port)
count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset],
port->interrupt_out_size-offset);
- if (count == 0) {
+ if (count == 0)
return;
- }
switch (priv->pkt_fmt) {
default:
@@ -851,26 +883,29 @@ send:
actual_size = count +
(priv->pkt_fmt == packet_format_1 ? 2 : 1);
- usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
- port->interrupt_out_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ port->interrupt_out_size,
+ port->interrupt_out_urb->transfer_buffer);
usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
port->interrupt_out_buffer, port->interrupt_out_size,
cypress_write_int_callback, port, priv->write_urb_interval);
- result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
- result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
priv->write_urb_in_use = 0;
cypress_set_dead(port);
}
spin_lock_irqsave(&priv->lock, flags);
- if (priv->cmd_ctrl) {
+ if (priv->cmd_ctrl)
priv->cmd_ctrl = 0;
- }
- priv->bytes_out += count; /* do not count the line control and size bytes */
+
+ /* do not count the line control and size bytes */
+ priv->bytes_out += count;
spin_unlock_irqrestore(&priv->lock, flags);
usb_serial_port_softint(port);
@@ -878,8 +913,9 @@ send:
/* returns how much space is available in the soft buffer */
-static int cypress_write_room(struct usb_serial_port *port)
+static int cypress_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -895,13 +931,14 @@ static int cypress_write_room(struct usb_serial_port *port)
}
-static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
__u8 status, control;
unsigned int result = 0;
unsigned long flags;
-
+
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
@@ -922,12 +959,13 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
}
-static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
-
+
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
@@ -942,63 +980,60 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
priv->cmd_ctrl = 1;
spin_unlock_irqrestore(&priv->lock, flags);
- return cypress_write(port, NULL, 0);
+ return cypress_write(tty, port, NULL, 0);
}
-static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
switch (cmd) {
- /* This code comes from drivers/char/serial.c and ftdi_sio.c */
- case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- else {
- char diff = priv->diff_status;
-
- if (diff == 0) {
- return -EIO; /* no change => error */
- }
-
- /* consume all events */
- priv->diff_status = 0;
-
- /* return 0 if caller wanted to know about these bits */
- if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||
- ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
- ((arg & TIOCM_CD) && (diff & UART_CD)) ||
- ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {
- return 0;
- }
- /* otherwise caller can't care less about what happened,
- * and so we continue to wait for more events.
- */
- }
+ /* This code comes from drivers/char/serial.c and ftdi_sio.c */
+ case TIOCMIWAIT:
+ while (priv != NULL) {
+ interruptible_sleep_on(&priv->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ else {
+ char diff = priv->diff_status;
+ if (diff == 0)
+ return -EIO; /* no change => error */
+
+ /* consume all events */
+ priv->diff_status = 0;
+
+ /* return 0 if caller wanted to know about
+ these bits */
+ if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & UART_CD)) ||
+ ((arg & TIOCM_CTS) && (diff & UART_CTS)))
+ return 0;
+ /* otherwise caller can't care less about what
+ * happened, and so we continue to wait for
+ * more events.
+ */
}
- return 0;
- break;
- default:
- break;
+ }
+ return 0;
+ default:
+ break;
}
-
dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
-
return -ENOIOCTLCMD;
} /* cypress_ioctl */
-static void cypress_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void cypress_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int data_bits, stop_bits, parity_type, parity_enable;
unsigned cflag, iflag;
unsigned long flags;
@@ -1007,8 +1042,6 @@ static void cypress_set_termios (struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- tty = port->tty;
-
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
if (priv->chiptype == CT_EARTHMATE) {
@@ -1060,28 +1093,24 @@ static void cypress_set_termios (struct usb_serial_port *port,
} else
parity_enable = parity_type = 0;
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5:
- data_bits = 0;
- break;
- case CS6:
- data_bits = 1;
- break;
- case CS7:
- data_bits = 2;
- break;
- case CS8:
- data_bits = 3;
- break;
- default:
- err("%s - CSIZE was set, but not CS5-CS8",
- __func__);
- data_bits = 3;
- }
- } else
+ switch (cflag & CSIZE) {
+ case CS5:
+ data_bits = 0;
+ break;
+ case CS6:
+ data_bits = 1;
+ break;
+ case CS7:
+ data_bits = 2;
+ break;
+ case CS8:
data_bits = 3;
-
+ break;
+ default:
+ err("%s - CSIZE was set, but not CS5-CS8",
+ __func__);
+ data_bits = 3;
+ }
spin_lock_irqsave(&priv->lock, flags);
oldlines = priv->line_control;
if ((cflag & CBAUD) == B0) {
@@ -1096,19 +1125,21 @@ static void cypress_set_termios (struct usb_serial_port *port,
"%d data_bits (+5)", __func__, stop_bits,
parity_enable, parity_type, data_bits);
- cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
- parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
+ cypress_serial_control(tty, port, tty_get_baud_rate(tty),
+ data_bits, stop_bits,
+ parity_enable, parity_type,
+ 0, CYPRESS_SET_CONFIG);
/* we perform a CYPRESS_GET_CONFIG so that the current settings are
* filled into the private structure this should confirm that all is
* working if it returns what we just set */
- cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
+ cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
/* Here we can define custom tty settings for devices; the main tty
* termios flag base comes from empeg.c */
spin_lock_irqsave(&priv->lock, flags);
- if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
+ if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
dbg("Using custom termios settings for a baud rate of "
"4800bps.");
/* define custom termios settings for NMEA protocol */
@@ -1142,20 +1173,21 @@ static void cypress_set_termios (struct usb_serial_port *port,
/* if necessary, set lines */
if (linechange) {
priv->cmd_ctrl = 1;
- cypress_write(port, NULL, 0);
+ cypress_write(tty, port, NULL, 0);
}
} /* cypress_set_termios */
/* returns amount of data still left in soft buffer */
-static int cypress_chars_in_buffer(struct usb_serial_port *port)
+static int cypress_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
-
+
spin_lock_irqsave(&priv->lock, flags);
chars = cypress_buf_data_avail(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1165,8 +1197,9 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port)
}
-static void cypress_throttle (struct usb_serial_port *port)
+static void cypress_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -1178,8 +1211,9 @@ static void cypress_throttle (struct usb_serial_port *port)
}
-static void cypress_unthrottle (struct usb_serial_port *port)
+static void cypress_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port);
int actually_throttled, result;
unsigned long flags;
@@ -1232,12 +1266,13 @@ static void cypress_read_int_callback(struct urb *urb)
/* precursor to disconnect so just go away */
return;
case -EPIPE:
- usb_clear_halt(port->serial->dev,0x81);
+ usb_clear_halt(port->serial->dev, 0x81);
break;
default:
/* something ugly is going on... */
- dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
- __func__, status);
+ dev_err(&urb->dev->dev,
+ "%s - unexpected nonzero read status received: %d\n",
+ __func__, status);
cypress_set_dead(port);
return;
}
@@ -1251,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb)
}
spin_unlock_irqrestore(&priv->lock, flags);
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
dbg("%s - bad tty pointer - exiting", __func__);
return;
@@ -1285,8 +1320,8 @@ static void cypress_read_int_callback(struct urb *urb)
goto continue_read;
}
- usb_serial_debug_data (debug, &port->dev, __func__,
- urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
spin_lock_irqsave(&priv->lock, flags);
/* check to see if status has changed */
@@ -1327,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb)
data[i]);
tty_insert_flip_char(tty, data[i], tty_flag);
}
- tty_flip_buffer_push(port->tty);
+ tty_flip_buffer_push(port->port.tty);
}
spin_lock_irqsave(&priv->lock, flags);
@@ -1339,13 +1374,14 @@ continue_read:
/* Continue trying to always read... unless the port has closed. */
- if (port->open_count > 0 && priv->comm_is_ok) {
+ if (port->port.count > 0 && priv->comm_is_ok) {
usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
usb_rcvintpipe(port->serial->dev,
port->interrupt_in_endpointAddress),
port->interrupt_in_urb->transfer_buffer,
port->interrupt_in_urb->transfer_buffer_length,
- cypress_read_int_callback, port, priv->read_urb_interval);
+ cypress_read_int_callback, port,
+ priv->read_urb_interval);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result) {
dev_err(&urb->dev->dev, "%s - failed resubmitting "
@@ -1369,42 +1405,43 @@ static void cypress_write_int_callback(struct urb *urb)
dbg("%s - port %d", __func__, port->number);
switch (status) {
- case 0:
- /* success */
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d",
+ __func__, status);
+ priv->write_urb_in_use = 0;
+ return;
+ case -EPIPE: /* no break needed; clear halt and resubmit */
+ if (!priv->comm_is_ok)
break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __func__, status);
- priv->write_urb_in_use = 0;
+ usb_clear_halt(port->serial->dev, 0x02);
+ /* error in the urb, so we have to resubmit it */
+ dbg("%s - nonzero write bulk status received: %d",
+ __func__, status);
+ port->interrupt_out_urb->transfer_buffer_length = 1;
+ port->interrupt_out_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
+ if (!result)
return;
- case -EPIPE: /* no break needed; clear halt and resubmit */
- if (!priv->comm_is_ok)
- break;
- usb_clear_halt(port->serial->dev, 0x02);
- /* error in the urb, so we have to resubmit it */
- dbg("%s - nonzero write bulk status received: %d",
- __func__, status);
- port->interrupt_out_urb->transfer_buffer_length = 1;
- port->interrupt_out_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
- if (!result)
- return;
- dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
- __func__, result);
- cypress_set_dead(port);
- break;
- default:
- dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
- __func__, status);
- cypress_set_dead(port);
- break;
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting write urb, error %d\n",
+ __func__, result);
+ cypress_set_dead(port);
+ break;
+ default:
+ dev_err(&urb->dev->dev,
+ "%s - unexpected nonzero write status received: %d\n",
+ __func__, status);
+ cypress_set_dead(port);
+ break;
}
-
priv->write_urb_in_use = 0;
-
+
/* send any buffered data */
cypress_send(port);
}
@@ -1486,7 +1523,8 @@ static void cypress_buf_clear(struct cypress_buf *cb)
static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
{
if (cb != NULL)
- return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size);
+ return (cb->buf_size + cb->buf_put - cb->buf_get)
+ % cb->buf_size;
else
return 0;
}
@@ -1502,7 +1540,8 @@ static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
static unsigned int cypress_buf_space_avail(struct cypress_buf *cb)
{
if (cb != NULL)
- return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size);
+ return (cb->buf_size + cb->buf_get - cb->buf_put - 1)
+ % cb->buf_size;
else
return 0;
}
@@ -1602,9 +1641,9 @@ static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf,
static int __init cypress_init(void)
{
int retval;
-
+
dbg("%s", __func__);
-
+
retval = usb_serial_register(&cypress_earthmate_device);
if (retval)
goto failed_em_register;
@@ -1632,23 +1671,23 @@ failed_em_register:
}
-static void __exit cypress_exit (void)
+static void __exit cypress_exit(void)
{
dbg("%s", __func__);
- usb_deregister (&cypress_driver);
- usb_serial_deregister (&cypress_earthmate_device);
- usb_serial_deregister (&cypress_hidcom_device);
- usb_serial_deregister (&cypress_ca42v2_device);
+ usb_deregister(&cypress_driver);
+ usb_serial_deregister(&cypress_earthmate_device);
+ usb_serial_deregister(&cypress_hidcom_device);
+ usb_serial_deregister(&cypress_ca42v2_device);
}
module_init(cypress_init);
module_exit(cypress_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index 0388065bb79..e772b01ac3a 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -54,7 +54,7 @@
#define UART_DSR 0x20 /* data set ready - flow control - device to host */
#define CONTROL_RTS 0x10 /* request to send - flow control - host to device */
#define UART_CTS 0x10 /* clear to send - flow control - device to host */
-#define UART_RI 0x10 /* ring indicator - modem - device to host */
+#define UART_RI 0x10 /* ring indicator - modem - device to host */
#define UART_CD 0x40 /* carrier detect - modem - device to host */
#define CYP_ERROR 0x08 /* received from input report - device to host */
/* Note - the below has nothing to to with the "feature report" reset */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 04a56f300ea..240aad1acaa 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -15,7 +15,7 @@
* Al Borchers (borchers@steinerpoint.com)
*
* (12/03/2001) gkh
-* switched to using port->open_count instead of private version.
+* switched to using port->port.count instead of private version.
* Removed port->active
*
* (04/08/2001) gb
@@ -229,8 +229,6 @@
* in case a wake up is lost.
* - Following Documentation/DocBook/kernel-locking.pdf no spin locks
* are held when calling copy_to/from_user or printk.
-*
-* $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $
*/
#include <linux/kernel.h>
@@ -243,7 +241,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/usb/serial.h>
@@ -443,22 +441,23 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible);
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout);
-static void digi_rx_throttle (struct usb_serial_port *port);
-static void digi_rx_unthrottle (struct usb_serial_port *port);
-static void digi_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
-static void digi_break_ctl(struct usb_serial_port *port, int break_state);
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file);
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static void digi_rx_throttle(struct tty_struct *tty);
+static void digi_rx_unthrottle(struct tty_struct *tty);
+static void digi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void digi_break_ctl(struct tty_struct *tty, int break_state);
+static int digi_tiocmget(struct tty_struct *tty, struct file *file);
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count);
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
static void digi_write_bulk_callback(struct urb *urb);
-static int digi_write_room(struct usb_serial_port *port);
-static int digi_chars_in_buffer(struct usb_serial_port *port);
-static int digi_open(struct usb_serial_port *port, struct file *filp);
-static void digi_close(struct usb_serial_port *port, struct file *filp);
+static int digi_write_room(struct tty_struct *tty);
+static int digi_chars_in_buffer(struct tty_struct *tty);
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_shutdown(struct usb_serial *serial);
@@ -487,7 +486,7 @@ static struct usb_device_id id_table_4 [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver digi_driver = {
.name = "digi_acceleport",
@@ -518,7 +517,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.chars_in_buffer = digi_chars_in_buffer,
.throttle = digi_rx_throttle,
.unthrottle = digi_rx_unthrottle,
- .ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
@@ -545,7 +543,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.chars_in_buffer = digi_chars_in_buffer,
.throttle = digi_rx_throttle,
.unthrottle = digi_rx_unthrottle,
- .ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
@@ -558,21 +555,22 @@ static struct usb_serial_driver digi_acceleport_4_device = {
/* Functions */
/*
-* Cond Wait Interruptible Timeout Irqrestore
-*
-* Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
-* so that wake ups are not lost if they occur between the unlock
-* and the sleep. In other words, spin_unlock_irqrestore and
-* interruptible_sleep_on_timeout are "atomic" with respect to
-* wake ups. This is used to implement condition variables.
-*
-* interruptible_sleep_on_timeout is deprecated and has been replaced
-* with the equivalent code.
-*/
+ * Cond Wait Interruptible Timeout Irqrestore
+ *
+ * Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
+ * so that wake ups are not lost if they occur between the unlock
+ * and the sleep. In other words, spin_unlock_irqrestore and
+ * interruptible_sleep_on_timeout are "atomic" with respect to
+ * wake ups. This is used to implement condition variables.
+ *
+ * interruptible_sleep_on_timeout is deprecated and has been replaced
+ * with the equivalent code.
+ */
static long cond_wait_interruptible_timeout_irqrestore(
wait_queue_head_t *q, long timeout,
spinlock_t *lock, unsigned long flags)
+__releases(lock)
{
DEFINE_WAIT(wait);
@@ -586,15 +584,16 @@ static long cond_wait_interruptible_timeout_irqrestore(
/*
-* Digi Wakeup Write
-*
-* Wake up port, line discipline, and tty processes sleeping
-* on writes.
-*/
+ * Digi Wakeup Write
+ *
+ * Wake up port, line discipline, and tty processes sleeping
+ * on writes.
+ */
static void digi_wakeup_write_lock(struct work_struct *work)
{
- struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work);
+ struct digi_port *priv =
+ container_of(work, struct digi_port, dp_wakeup_work);
struct usb_serial_port *port = priv->dp_port;
unsigned long flags;
@@ -605,20 +604,20 @@ static void digi_wakeup_write_lock(struct work_struct *work)
static void digi_wakeup_write(struct usb_serial_port *port)
{
- tty_wakeup(port->tty);
+ tty_wakeup(port->port.tty);
}
/*
-* Digi Write OOB Command
-*
-* Write commands on the out of band port. Commands are 4
-* bytes each, multiple commands can be sent at once, and
-* no command will be split across USB packets. Returns 0
-* if successful, -EINTR if interrupted while sleeping and
-* the interruptible flag is true, or a negative error
-* returned by usb_submit_urb.
-*/
+ * Digi Write OOB Command
+ *
+ * Write commands on the out of band port. Commands are 4
+ * bytes each, multiple commands can be sent at once, and
+ * no command will be split across USB packets. Returns 0
+ * if successful, -EINTR if interrupted while sleeping and
+ * the interruptible flag is true, or a negative error
+ * returned by usb_submit_urb.
+ */
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible)
@@ -633,8 +632,8 @@ static int digi_write_oob_command(struct usb_serial_port *port,
dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count);
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
- while(count > 0) {
- while(oob_port->write_urb->status == -EINPROGRESS
+ while (count > 0) {
+ while (oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use) {
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -651,7 +650,8 @@ static int digi_write_oob_command(struct usb_serial_port *port,
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
@@ -666,16 +666,16 @@ static int digi_write_oob_command(struct usb_serial_port *port,
/*
-* Digi Write In Band Command
-*
-* Write commands on the given port. Commands are 4
-* bytes each, multiple commands can be sent at once, and
-* no command will be split across USB packets. If timeout
-* is non-zero, write in band command will return after
-* waiting unsuccessfully for the URB status to clear for
-* timeout ticks. Returns 0 if successful, or a negative
-* error returned by digi_write.
-*/
+ * Digi Write In Band Command
+ *
+ * Write commands on the given port. Commands are 4
+ * bytes each, multiple commands can be sent at once, and
+ * no command will be split across USB packets. If timeout
+ * is non-zero, write in band command will return after
+ * waiting unsuccessfully for the URB status to clear for
+ * timeout ticks. Returns 0 if successful, or a negative
+ * error returned by digi_write.
+ */
static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout)
@@ -695,9 +695,10 @@ static int digi_write_inb_command(struct usb_serial_port *port,
timeout = ULONG_MAX;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- while(count > 0 && ret == 0) {
- while((port->write_urb->status == -EINPROGRESS
- || priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
+ while (count > 0 && ret == 0) {
+ while ((port->write_urb->status == -EINPROGRESS
+ || priv->dp_write_urb_in_use)
+ && time_before(jiffies, timeout)) {
cond_wait_interruptible_timeout_irqrestore(
&port->write_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -728,7 +729,8 @@ static int digi_write_inb_command(struct usb_serial_port *port,
}
port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
count -= len;
@@ -746,14 +748,14 @@ static int digi_write_inb_command(struct usb_serial_port *port,
/*
-* Digi Set Modem Signals
-*
-* Sets or clears DTR and RTS on the port, according to the
-* modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags
-* for the modem_signals argument. Returns 0 if successful,
-* -EINTR if interrupted while sleeping, or a non-zero error
-* returned by usb_submit_urb.
-*/
+ * Digi Set Modem Signals
+ *
+ * Sets or clears DTR and RTS on the port, according to the
+ * modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags
+ * for the modem_signals argument. Returns 0 if successful,
+ * -EINTR if interrupted while sleeping, or a non-zero error
+ * returned by usb_submit_urb.
+ */
static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible)
@@ -761,7 +763,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
int ret;
struct digi_port *port_priv = usb_get_serial_port_data(port);
- struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
+ struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned char *data = oob_port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -773,7 +775,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock(&port_priv->dp_port_lock);
- while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) {
+ while (oob_port->write_urb->status == -EINPROGRESS ||
+ oob_priv->dp_write_urb_in_use) {
spin_unlock(&port_priv->dp_port_lock);
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -785,17 +788,20 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
}
data[0] = DIGI_CMD_SET_DTR_SIGNAL;
data[1] = port_priv->dp_port_num;
- data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
+ data[2] = (modem_signals & TIOCM_DTR) ?
+ DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
data[3] = 0;
data[4] = DIGI_CMD_SET_RTS_SIGNAL;
data[5] = port_priv->dp_port_num;
- data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
+ data[6] = (modem_signals & TIOCM_RTS) ?
+ DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
data[7] = 0;
oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -809,16 +815,16 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
}
/*
-* Digi Transmit Idle
-*
-* Digi transmit idle waits, up to timeout ticks, for the transmitter
-* to go idle. It returns 0 if successful or a negative error.
-*
-* There are race conditions here if more than one process is calling
-* digi_transmit_idle on the same port at the same time. However, this
-* is only called from close, and only one process can be in close on a
-* port at a time, so its ok.
-*/
+ * Digi Transmit Idle
+ *
+ * Digi transmit idle waits, up to timeout ticks, for the transmitter
+ * to go idle. It returns 0 if successful or a negative error.
+ *
+ * There are race conditions here if more than one process is calling
+ * digi_transmit_idle on the same port at the same time. However, this
+ * is only called from close, and only one process can be in close on a
+ * port at a time, so its ok.
+ */
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout)
@@ -837,12 +843,13 @@ static int digi_transmit_idle(struct usb_serial_port *port,
timeout += jiffies;
- if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0)
+ ret = digi_write_inb_command(port, buf, 2, timeout - jiffies);
+ if (ret != 0)
return ret;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
+ while (time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
cond_wait_interruptible_timeout_irqrestore(
&priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -857,9 +864,10 @@ static int digi_transmit_idle(struct usb_serial_port *port,
}
-static void digi_rx_throttle(struct usb_serial_port *port)
+static void digi_rx_throttle(struct tty_struct *tty)
{
unsigned long flags;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
@@ -873,10 +881,11 @@ static void digi_rx_throttle(struct usb_serial_port *port)
}
-static void digi_rx_unthrottle(struct usb_serial_port *port)
+static void digi_rx_unthrottle(struct tty_struct *tty)
{
int ret = 0;
unsigned long flags;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
@@ -901,26 +910,25 @@ static void digi_rx_unthrottle(struct usb_serial_port *port)
}
-static void digi_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void digi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
-
struct digi_port *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int iflag = tty->termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned char buf[32];
unsigned int modem_signals;
- int arg,ret;
+ int arg, ret;
int i = 0;
speed_t baud;
dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
/* set baud rate */
- if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) {
+ baud = tty_get_baud_rate(tty);
+ if (baud != tty_termios_baud_rate(old_termios)) {
arg = -1;
/* reassert DTR and (maybe) RTS on transition from B0 */
@@ -934,30 +942,30 @@ static void digi_set_termios(struct usb_serial_port *port,
digi_set_modem_signals(port, modem_signals, 1);
}
switch (baud) {
- /* drop DTR and RTS on transition to B0 */
- case 0: digi_set_modem_signals(port, 0, 1); break;
- case 50: arg = DIGI_BAUD_50; break;
- case 75: arg = DIGI_BAUD_75; break;
- case 110: arg = DIGI_BAUD_110; break;
- case 150: arg = DIGI_BAUD_150; break;
- case 200: arg = DIGI_BAUD_200; break;
- case 300: arg = DIGI_BAUD_300; break;
- case 600: arg = DIGI_BAUD_600; break;
- case 1200: arg = DIGI_BAUD_1200; break;
- case 1800: arg = DIGI_BAUD_1800; break;
- case 2400: arg = DIGI_BAUD_2400; break;
- case 4800: arg = DIGI_BAUD_4800; break;
- case 9600: arg = DIGI_BAUD_9600; break;
- case 19200: arg = DIGI_BAUD_19200; break;
- case 38400: arg = DIGI_BAUD_38400; break;
- case 57600: arg = DIGI_BAUD_57600; break;
- case 115200: arg = DIGI_BAUD_115200; break;
- case 230400: arg = DIGI_BAUD_230400; break;
- case 460800: arg = DIGI_BAUD_460800; break;
- default:
- arg = DIGI_BAUD_9600;
- baud = 9600;
- break;
+ /* drop DTR and RTS on transition to B0 */
+ case 0: digi_set_modem_signals(port, 0, 1); break;
+ case 50: arg = DIGI_BAUD_50; break;
+ case 75: arg = DIGI_BAUD_75; break;
+ case 110: arg = DIGI_BAUD_110; break;
+ case 150: arg = DIGI_BAUD_150; break;
+ case 200: arg = DIGI_BAUD_200; break;
+ case 300: arg = DIGI_BAUD_300; break;
+ case 600: arg = DIGI_BAUD_600; break;
+ case 1200: arg = DIGI_BAUD_1200; break;
+ case 1800: arg = DIGI_BAUD_1800; break;
+ case 2400: arg = DIGI_BAUD_2400; break;
+ case 4800: arg = DIGI_BAUD_4800; break;
+ case 9600: arg = DIGI_BAUD_9600; break;
+ case 19200: arg = DIGI_BAUD_19200; break;
+ case 38400: arg = DIGI_BAUD_38400; break;
+ case 57600: arg = DIGI_BAUD_57600; break;
+ case 115200: arg = DIGI_BAUD_115200; break;
+ case 230400: arg = DIGI_BAUD_230400; break;
+ case 460800: arg = DIGI_BAUD_460800; break;
+ default:
+ arg = DIGI_BAUD_9600;
+ baud = 9600;
+ break;
}
if (arg != -1) {
buf[i++] = DIGI_CMD_SET_BAUD_RATE;
@@ -1083,14 +1091,16 @@ static void digi_set_termios(struct usb_serial_port *port,
buf[i++] = arg;
buf[i++] = 0;
}
- if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
+ ret = digi_write_oob_command(port, buf, i, 1);
+ if (ret != 0)
dbg("digi_set_termios: write oob failed, ret=%d", ret);
tty_encode_baud_rate(tty, baud, baud);
}
-static void digi_break_ctl(struct usb_serial_port *port, int break_state)
+static void digi_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned char buf[4];
buf[0] = DIGI_CMD_BREAK_CONTROL;
@@ -1101,8 +1111,9 @@ static void digi_break_ctl(struct usb_serial_port *port, int break_state)
}
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
+static int digi_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
@@ -1116,9 +1127,10 @@ static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
}
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
@@ -1132,30 +1144,11 @@ static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
}
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct digi_port *priv = usb_get_serial_port_data(port);
- dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd);
-
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return 0;
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
- }
- return -ENOIOCTLCMD;
-
-}
-
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
- int ret,data_len,new_len;
+ int ret, data_len, new_len;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -1173,7 +1166,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
spin_lock_irqsave(&priv->dp_port_lock, flags);
/* wait for urb status clear to submit another urb */
- if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) {
+ if (port->write_urb->status == -EINPROGRESS ||
+ priv->dp_write_urb_in_use) {
/* buffer data if count is 1 (probably put_char) if possible */
if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
@@ -1208,7 +1202,8 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
/* copy in new data */
memcpy(data, buf, new_len);
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
ret = new_len;
priv->dp_out_buf_len = 0;
@@ -1222,7 +1217,7 @@ static int digi_write(struct usb_serial_port *port, const unsigned char *buf, in
dbg("digi_write: returning %d", ret);
return ret;
-}
+}
static void digi_write_bulk_callback(struct urb *urb)
{
@@ -1237,13 +1232,13 @@ static void digi_write_bulk_callback(struct urb *urb)
dbg("digi_write_bulk_callback: TOP, urb->status=%d", status);
/* port and serial sanity check */
- if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
+ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
err("%s: port or port->private is NULL, status=%d",
__func__, status);
return;
}
serial = port->serial;
- if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
+ if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) {
err("%s: serial or serial->private is NULL, status=%d",
__func__, status);
return;
@@ -1262,17 +1257,19 @@ static void digi_write_bulk_callback(struct urb *urb)
/* try to send any buffered data on this port, if it is open */
spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
- if (port->open_count && port->write_urb->status != -EINPROGRESS
+ if (port->port.count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0) {
*((unsigned char *)(port->write_urb->transfer_buffer))
= (unsigned char)DIGI_CMD_SEND_DATA;
- *((unsigned char *)(port->write_urb->transfer_buffer)+1)
+ *((unsigned char *)(port->write_urb->transfer_buffer) + 1)
= (unsigned char)priv->dp_out_buf_len;
- port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2;
+ port->write_urb->transfer_buffer_length =
+ priv->dp_out_buf_len + 2;
port->write_urb->dev = serial->dev;
- memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf,
+ memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf,
priv->dp_out_buf_len);
- if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+ ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (ret == 0) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
@@ -1289,16 +1286,17 @@ static void digi_write_bulk_callback(struct urb *urb)
__func__, ret, priv->dp_port_num);
}
-static int digi_write_room(struct usb_serial_port *port)
+static int digi_write_room(struct tty_struct *tty)
{
-
- int room;
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
+ int room;
unsigned long flags = 0;
spin_lock_irqsave(&priv->dp_port_lock, flags);
- if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use)
+ if (port->write_urb->status == -EINPROGRESS ||
+ priv->dp_write_urb_in_use)
room = 0;
else
room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
@@ -1309,12 +1307,11 @@ static int digi_write_room(struct usb_serial_port *port)
}
-static int digi_chars_in_buffer(struct usb_serial_port *port)
+static int digi_chars_in_buffer(struct tty_struct *tty)
{
-
+ struct usb_serial_port *port = tty->driver_data;
struct digi_port *priv = usb_get_serial_port_data(port);
-
if (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) {
dbg("digi_chars_in_buffer: port=%d, chars=%d",
@@ -1330,7 +1327,8 @@ static int digi_chars_in_buffer(struct usb_serial_port *port)
}
-static int digi_open(struct usb_serial_port *port, struct file *filp)
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
int ret;
unsigned char buf[32];
@@ -1339,7 +1337,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
unsigned long flags = 0;
dbg("digi_open: TOP: port=%d, open_count=%d",
- priv->dp_port_num, port->open_count);
+ priv->dp_port_num, port->port.count);
/* be sure the device is started up */
if (digi_startup_device(port->serial) != 0)
@@ -1354,7 +1352,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
/* wait for a close in progress to finish */
- while(priv->dp_in_close) {
+ while (priv->dp_in_close) {
cond_wait_interruptible_timeout_irqrestore(
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags);
@@ -1364,7 +1362,7 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-
+
/* read modem signals automatically whenever they change */
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
buf[1] = priv->dp_port_num;
@@ -1377,13 +1375,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[7] = 0;
- if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0)
+ ret = digi_write_oob_command(port, buf, 8, 1);
+ if (ret != 0)
dbg("digi_open: write oob failed, ret=%d", ret);
/* set termios settings */
- not_termios.c_cflag = ~port->tty->termios->c_cflag;
- not_termios.c_iflag = ~port->tty->termios->c_iflag;
- digi_set_termios(port, &not_termios);
+ if (tty) {
+ not_termios.c_cflag = ~tty->termios->c_cflag;
+ not_termios.c_iflag = ~tty->termios->c_iflag;
+ digi_set_termios(tty, port, &not_termios);
+ }
/* set DTR and RTS */
digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
@@ -1392,16 +1393,16 @@ static int digi_open(struct usb_serial_port *port, struct file *filp)
}
-static void digi_close(struct usb_serial_port *port, struct file *filp)
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
DEFINE_WAIT(wait);
int ret;
unsigned char buf[32];
- struct tty_struct *tty = port->tty;
struct digi_port *priv = usb_get_serial_port_data(port);
dbg("digi_close: TOP: port=%d, open_count=%d",
- priv->dp_port_num, port->open_count);
+ priv->dp_port_num, port->port.count);
mutex_lock(&port->serial->disc_mutex);
/* if disconnected, just clear flags */
@@ -1426,9 +1427,8 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
if (port->serial->dev) {
/* wait for transmit idle */
- if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
+ if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
- }
/* drop DTR and RTS */
digi_set_modem_signals(port, 0, 0);
@@ -1462,11 +1462,13 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[19] = 0;
- if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0)
+ ret = digi_write_oob_command(port, buf, 20, 0);
+ if (ret != 0)
dbg("digi_close: write oob failed, ret=%d", ret);
/* wait for final commands on oob port to complete */
- prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(&priv->dp_flush_wait, &wait,
+ TASK_INTERRUPTIBLE);
schedule_timeout(DIGI_CLOSE_TIMEOUT);
finish_wait(&priv->dp_flush_wait, &wait);
@@ -1486,15 +1488,15 @@ exit:
/*
-* Digi Startup Device
-*
-* Starts reads on all ports. Must be called AFTER startup, with
-* urbs initialized. Returns 0 if successful, non-zero error otherwise.
-*/
+ * Digi Startup Device
+ *
+ * Starts reads on all ports. Must be called AFTER startup, with
+ * urbs initialized. Returns 0 if successful, non-zero error otherwise.
+ */
static int digi_startup_device(struct usb_serial *serial)
{
- int i,ret = 0;
+ int i, ret = 0;
struct digi_serial *serial_priv = usb_get_serial_data(serial);
struct usb_serial_port *port;
@@ -1512,7 +1514,8 @@ static int digi_startup_device(struct usb_serial *serial)
for (i = 0; i < serial->type->num_ports + 1; i++) {
port = serial->port[i];
port->write_urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
+ ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (ret != 0) {
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__func__, ret, i);
break;
@@ -1533,7 +1536,7 @@ static int digi_startup(struct usb_serial *serial)
/* allocate the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
- for(i = 0; i < serial->type->num_ports + 1; i++) {
+ for (i = 0; i < serial->type->num_ports + 1; i++) {
/* allocate port private structure */
priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
if (priv == NULL) {
@@ -1596,7 +1599,7 @@ static void digi_shutdown(struct usb_serial *serial)
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
- for(i = 0; i < serial->type->num_ports + 1; i++)
+ for (i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
kfree(usb_get_serial_data(serial));
}
@@ -1619,7 +1622,7 @@ static void digi_read_bulk_callback(struct urb *urb)
return;
}
if (port->serial == NULL ||
- (serial_priv=usb_get_serial_data(port->serial)) == NULL) {
+ (serial_priv = usb_get_serial_data(port->serial)) == NULL) {
err("%s: serial is bad or serial->private is NULL, status=%d",
__func__, status);
return;
@@ -1643,45 +1646,46 @@ static void digi_read_bulk_callback(struct urb *urb)
/* continue read */
urb->dev = port->serial->dev;
- if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret != 0) {
err("%s: failed resubmitting urb, ret=%d, port=%d",
__func__, ret, priv->dp_port_num);
}
}
-/*
-* Digi Read INB Callback
-*
-* Digi Read INB Callback handles reads on the in band ports, sending
-* the data on to the tty subsystem. When called we know port and
-* port->private are not NULL and port->serial has been validated.
-* It returns 0 if successful, 1 if successful but the port is
-* throttled, and -1 if the sanity checks failed.
-*/
+/*
+ * Digi Read INB Callback
+ *
+ * Digi Read INB Callback handles reads on the in band ports, sending
+ * the data on to the tty subsystem. When called we know port and
+ * port->private are not NULL and port->serial has been validated.
+ * It returns 0 if successful, 1 if successful but the port is
+ * throttled, and -1 if the sanity checks failed.
+ */
static int digi_read_inb_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
int port_status = ((unsigned char *)urb->transfer_buffer)[2];
- unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
- int flag,throttled;
+ unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+ int flag, throttled;
int i;
int status = urb->status;
/* do not process callbacks on closed ports */
/* but do continue the read chain */
- if (port->open_count == 0)
+ if (port->port.count == 0)
return 0;
/* short/multiple packet check */
if (urb->actual_length != len + 2) {
- err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
+ err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
"port=%d, opcode=%d, len=%d, actual_length=%d, "
"status=%d", __func__, status, priv->dp_port_num,
opcode, len, urb->actual_length, port_status);
@@ -1723,8 +1727,9 @@ static int digi_read_inb_callback(struct urb *urb)
if (flag == TTY_NORMAL)
tty_insert_flip_string(tty, data, len);
else {
- for(i = 0; i < len; i++)
- tty_insert_flip_char(tty, data[i], flag);
+ for (i = 0; i < len; i++)
+ tty_insert_flip_char(tty,
+ data[i], flag);
}
tty_flip_buffer_push(tty);
}
@@ -1736,19 +1741,19 @@ static int digi_read_inb_callback(struct urb *urb)
else if (opcode != DIGI_CMD_RECEIVE_DATA)
dbg("%s: unknown opcode: %d", __func__, opcode);
- return(throttled ? 1 : 0);
+ return throttled ? 1 : 0;
}
-/*
-* Digi Read OOB Callback
-*
-* Digi Read OOB Callback handles reads on the out of band port.
-* When called we know port and port->private are not NULL and
-* the port->serial is valid. It returns 0 if successful, and
-* -1 if the sanity checks failed.
-*/
+/*
+ * Digi Read OOB Callback
+ *
+ * Digi Read OOB Callback handles reads on the out of band port.
+ * When called we know port and port->private are not NULL and
+ * the port->serial is valid. It returns 0 if successful, and
+ * -1 if the sanity checks failed.
+ */
static int digi_read_oob_callback(struct urb *urb)
{
@@ -1758,12 +1763,13 @@ static int digi_read_oob_callback(struct urb *urb)
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode, line, status, val;
int i;
+ unsigned int rts;
dbg("digi_read_oob_callback: port=%d, len=%d",
priv->dp_port_num, urb->actual_length);
/* handle each oob command */
- for(i = 0; i < urb->actual_length - 3;) {
+ for (i = 0; i < urb->actual_length - 3;) {
opcode = ((unsigned char *)urb->transfer_buffer)[i++];
line = ((unsigned char *)urb->transfer_buffer)[i++];
status = ((unsigned char *)urb->transfer_buffer)[i++];
@@ -1777,27 +1783,29 @@ static int digi_read_oob_callback(struct urb *urb)
port = serial->port[line];
- if ((priv=usb_get_serial_port_data(port)) == NULL)
+ priv = usb_get_serial_port_data(port);
+ if (priv == NULL)
return -1;
+ rts = 0;
+ if (port->port.count)
+ rts = port->port.tty->termios->c_cflag & CRTSCTS;
+
if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
/* convert from digi flags to termiox flags */
if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
priv->dp_modem_signals |= TIOCM_CTS;
/* port must be open to use tty struct */
- if (port->open_count
- && port->tty->termios->c_cflag & CRTSCTS) {
- port->tty->hw_stopped = 0;
+ if (rts) {
+ port->port.tty->hw_stopped = 0;
digi_wakeup_write(port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */
- if (port->open_count
- && port->tty->termios->c_cflag & CRTSCTS) {
- port->tty->hw_stopped = 1;
- }
+ if (rts)
+ port->port.tty->hw_stopped = 1;
}
if (val & DIGI_READ_INPUT_SIGNALS_DSR)
priv->dp_modem_signals |= TIOCM_DSR;
@@ -1834,7 +1842,7 @@ static int __init digi_init(void)
if (retval)
goto failed_acceleport_2_device;
retval = usb_serial_register(&digi_acceleport_4_device);
- if (retval)
+ if (retval)
goto failed_acceleport_4_device;
retval = usb_register(&digi_driver);
if (retval)
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index c5ec309a3cb..a6ab5b58d9c 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -11,36 +11,39 @@
* it under the terms of the GNU General Public License, as published by
* the Free Software Foundation, version 2.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
* (07/16/2001) gb
- * remove unused code in empeg_close() (thanks to Oliver Neukum for pointing this
- * out) and rewrote empeg_set_termios().
- *
+ * remove unused code in empeg_close() (thanks to Oliver Neukum for
+ * pointing this out) and rewrote empeg_set_termios().
+ *
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* (01/22/2001) gb
- * Added write_room() and chars_in_buffer() support.
- *
+ * Added write_room() and chars_in_buffer() support.
+ *
* (12/21/2000) gb
* Moved termio stuff inside the port->active check.
* Moved MOD_DEC_USE_COUNT to end of empeg_close().
- *
+ *
* (12/03/2000) gb
- * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open()
- * This notifies the tty driver that the termios have changed.
- *
+ * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to
+ * empeg_open(). This notifies the tty driver that the termios have
+ * changed.
+ *
* (11/13/2000) gb
- * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
- * (It only needs to be set once - Doh!)
- *
+ * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
+ * empeg_open() (It only needs to be set once - Doh!)
+ *
* (11/11/2000) gb
* Updated to work with id_table structure.
- *
+ *
* (11/04/2000) gb
* Forked this from visor.c, and hacked it up to work with an
* Empeg ltd. empeg-car player. Constructive criticism welcomed.
@@ -48,7 +51,7 @@
* use of his code, and for his guidance, advice and patience. :)
* A 'Thank You' is in order for John Ripley of Empeg ltd for his
* advice, and patience too.
- *
+ *
*/
#include <linux/kernel.h>
@@ -60,7 +63,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -77,31 +80,30 @@ static int debug;
#define EMPEG_PRODUCT_ID 0x0001
/* function prototypes for an empeg-car player */
-static int empeg_open (struct usb_serial_port *port, struct file *filp);
-static void empeg_close (struct usb_serial_port *port, struct file *filp);
-static int empeg_write (struct usb_serial_port *port,
- const unsigned char *buf,
- int count);
-static int empeg_write_room (struct usb_serial_port *port);
-static int empeg_chars_in_buffer (struct usb_serial_port *port);
-static void empeg_throttle (struct usb_serial_port *port);
-static void empeg_unthrottle (struct usb_serial_port *port);
-static int empeg_startup (struct usb_serial *serial);
-static void empeg_shutdown (struct usb_serial *serial);
-static int empeg_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static void empeg_write_bulk_callback (struct urb *urb);
-static void empeg_read_bulk_callback (struct urb *urb);
+static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf,
+ int count);
+static int empeg_write_room(struct tty_struct *tty);
+static int empeg_chars_in_buffer(struct tty_struct *tty);
+static void empeg_throttle(struct tty_struct *tty);
+static void empeg_unthrottle(struct tty_struct *tty);
+static int empeg_startup(struct usb_serial *serial);
+static void empeg_shutdown(struct usb_serial *serial);
+static void empeg_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void empeg_write_bulk_callback(struct urb *urb);
+static void empeg_read_bulk_callback(struct urb *urb);
static struct usb_device_id id_table [] = {
{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver empeg_driver = {
.name = "empeg",
@@ -125,7 +127,6 @@ static struct usb_serial_driver empeg_device = {
.unthrottle = empeg_unthrottle,
.attach = empeg_startup,
.shutdown = empeg_shutdown,
- .ioctl = empeg_ioctl,
.set_termios = empeg_set_termios,
.write = empeg_write,
.write_room = empeg_write_room,
@@ -145,7 +146,8 @@ static int bytes_out;
/******************************************************************************
* Empeg specific driver functions
******************************************************************************/
-static int empeg_open (struct usb_serial_port *port, struct file *filp)
+static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
@@ -153,7 +155,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
/* Force default termio settings */
- empeg_set_termios (port, NULL) ;
+ empeg_set_termios(tty, port, NULL) ;
bytes_in = 0;
bytes_out = 0;
@@ -161,7 +163,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
usb_fill_bulk_urb(
port->read_urb,
- serial->dev,
+ serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -172,13 +174,16 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
return result;
}
-static void empeg_close (struct usb_serial_port *port, struct file * filp)
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
@@ -189,7 +194,8 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp)
}
-static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct urb *urb;
@@ -203,11 +209,10 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
dbg("%s - port %d", __func__, port->number);
while (count > 0) {
-
/* try to find a free urb in our list of them */
urb = NULL;
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]->status != -EINPROGRESS) {
@@ -216,7 +221,7 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
}
}
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
if (urb == NULL) {
dbg("%s - no more free urbs", __func__);
@@ -224,25 +229,27 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
+ dev_err(&port->dev,
+ "%s no more kernel memory...\n",
+ __func__);
goto exit;
}
}
- transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
- memcpy (urb->transfer_buffer, current_position, transfer_size);
+ memcpy(urb->transfer_buffer, current_position, transfer_size);
usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
/* build up our urb */
- usb_fill_bulk_urb (
+ usb_fill_bulk_urb(
urb,
serial->dev,
usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
+ port->bulk_out_endpointAddress),
urb->transfer_buffer,
transfer_size,
empeg_write_bulk_callback,
@@ -262,66 +269,57 @@ static int empeg_write (struct usb_serial_port *port, const unsigned char *buf,
bytes_out += transfer_size;
}
-
exit:
return bytes_sent;
-
-}
+}
-static int empeg_write_room (struct usb_serial_port *port)
+static int empeg_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int room = 0;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
-
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
/* tally up the number of bytes available */
for (i = 0; i < NUM_URBS; ++i) {
- if (write_urb_pool[i]->status != -EINPROGRESS) {
+ if (write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
- }
- }
-
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+ }
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
dbg("%s - returns %d", __func__, room);
-
- return (room);
+ return room;
}
-static int empeg_chars_in_buffer (struct usb_serial_port *port)
+static int empeg_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int chars = 0;
dbg("%s - port %d", __func__, port->number);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
/* tally up the number of bytes waiting */
for (i = 0; i < NUM_URBS; ++i) {
- if (write_urb_pool[i]->status == -EINPROGRESS) {
+ if (write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
dbg("%s - returns %d", __func__, chars);
-
- return (chars);
-
+ return chars;
}
-static void empeg_write_bulk_callback (struct urb *urb)
+static void empeg_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -338,7 +336,7 @@ static void empeg_write_bulk_callback (struct urb *urb)
}
-static void empeg_read_bulk_callback (struct urb *urb)
+static void empeg_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
@@ -354,9 +352,9 @@ static void empeg_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-
- tty = port->tty;
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
@@ -368,7 +366,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
/* Continue trying to always read */
usb_fill_bulk_urb(
port->read_urb,
- port->serial->dev,
+ port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -379,38 +377,39 @@ static void empeg_read_bulk_callback (struct urb *urb)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&urb->dev->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
-static void empeg_throttle (struct usb_serial_port *port)
+static void empeg_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
}
-static void empeg_unthrottle (struct usb_serial_port *port)
+static void empeg_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int result;
-
dbg("%s - port %d", __func__, port->number);
port->read_urb->dev = port->serial->dev;
-
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
-
- return;
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
}
-static int empeg_startup (struct usb_serial *serial)
+static int empeg_startup(struct usb_serial *serial)
{
int r;
@@ -422,7 +421,7 @@ static int empeg_startup (struct usb_serial *serial)
return -ENODEV;
}
dbg("%s - reset config", __func__);
- r = usb_reset_configuration (serial->dev);
+ r = usb_reset_configuration(serial->dev);
/* continue on with initialization */
return r;
@@ -430,34 +429,27 @@ static int empeg_startup (struct usb_serial *serial)
}
-static void empeg_shutdown (struct usb_serial *serial)
+static void empeg_shutdown(struct usb_serial *serial)
{
- dbg ("%s", __func__);
-}
-
-
-static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
- return -ENOIOCTLCMD;
+ dbg("%s", __func__);
}
-static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void empeg_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
dbg("%s - port %d", __func__, port->number);
/*
- * The empeg-car player wants these particular tty settings.
- * You could, for example, change the baud rate, however the
- * player only supports 115200 (currently), so there is really
- * no point in support for changes to the tty settings.
- * (at least for now)
- *
- * The default requirements for this device are:
- */
+ * The empeg-car player wants these particular tty settings.
+ * You could, for example, change the baud rate, however the
+ * player only supports 115200 (currently), so there is really
+ * no point in support for changes to the tty settings.
+ * (at least for now)
+ *
+ * The default requirements for this device are:
+ */
termios->c_iflag
&= ~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
@@ -491,18 +483,18 @@ static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *ol
* this is bad as it opens up the possibility of dropping bytes
* on the floor. We don't want to drop bytes on the floor. :)
*/
- port->tty->low_latency = 1;
- tty_encode_baud_rate(port->tty, 115200, 115200);
+ tty->low_latency = 1;
+ tty_encode_baud_rate(tty, 115200, 115200);
}
-static int __init empeg_init (void)
+static int __init empeg_init(void)
{
struct urb *urb;
int i, retval;
- /* create our write urb pool and transfer buffers */
- spin_lock_init (&write_urb_pool_lock);
+ /* create our write urb pool and transfer buffers */
+ spin_lock_init(&write_urb_pool_lock);
for (i = 0; i < NUM_URBS; ++i) {
urb = usb_alloc_urb(0, GFP_KERNEL);
write_urb_pool[i] = urb;
@@ -511,9 +503,10 @@ static int __init empeg_init (void)
continue;
}
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.",
+ err("%s - out of memory for urb buffers.",
__func__);
continue;
}
@@ -542,36 +535,36 @@ failed_usb_serial_register:
}
-static void __exit empeg_exit (void)
+static void __exit empeg_exit(void)
{
int i;
unsigned long flags;
usb_deregister(&empeg_driver);
- usb_serial_deregister (&empeg_device);
+ usb_serial_deregister(&empeg_device);
- spin_lock_irqsave (&write_urb_pool_lock, flags);
+ spin_lock_irqsave(&write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]) {
- /* FIXME - uncomment the following usb_kill_urb call when
- * the host controllers get fixed to set urb->dev = NULL after
- * the urb is finished. Otherwise this call oopses. */
+ /* FIXME - uncomment the following usb_kill_urb call
+ * when the host controllers get fixed to set urb->dev
+ * = NULL after the urb is finished. Otherwise this
+ * call oopses. */
/* usb_kill_urb(write_urb_pool[i]); */
kfree(write_urb_pool[i]->transfer_buffer);
- usb_free_urb (write_urb_pool[i]);
+ usb_free_urb(write_urb_pool[i]);
}
}
-
- spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+ spin_unlock_irqrestore(&write_urb_pool_lock, flags);
}
module_init(empeg_init);
module_exit(empeg_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index cc4fbd9d60b..711e84f6ed8 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -20,7 +20,8 @@
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
-int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+int ezusb_writememory(struct usb_serial *serial, int address,
+ unsigned char *data, int length, __u8 request)
{
int result;
unsigned char *transfer_buffer;
@@ -33,26 +34,27 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
transfer_buffer = kmemdup(data, length, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, length);
return -ENOMEM;
}
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
- kfree (transfer_buffer);
+ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ request, 0x40, address, 0, transfer_buffer, length, 3000);
+ kfree(transfer_buffer);
return result;
}
+EXPORT_SYMBOL_GPL(ezusb_writememory);
-int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
{
int response;
/* dbg("%s - %d", __func__, reset_bit); */
- response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+ response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0)
- dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
+ dev_err(&serial->dev->dev, "%s- %d failed\n",
+ __func__, reset_bit);
return response;
}
-
-
-EXPORT_SYMBOL_GPL(ezusb_writememory);
EXPORT_SYMBOL_GPL(ezusb_set_reset);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0ff4a3971e4..83871725014 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -12,7 +12,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
@@ -25,7 +26,8 @@
/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
/* Thanx to FTDI for so kindly providing details of the protocol required */
/* to talk to the device */
-/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
+/* Thanx to gkh and the rest of the usb dev group for all code I have
+ assimilated :-) */
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -36,7 +38,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/serial.h>
#include <linux/usb/serial.h>
@@ -55,17 +57,22 @@ static __u16 product;
struct ftdi_private {
ftdi_chip_type_t chip_type;
- /* type of the device, either SIO or FT8U232AM */
+ /* type of device, either SIO or FT8U232AM */
int baud_base; /* baud base clock for divisor setting */
- int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+ int custom_divisor; /* custom_divisor kludge, this is for
+ baud_base (different from what goes to the
+ chip!) */
__u16 last_set_data_urb_value ;
- /* the last data state set - needed for doing a break */
- int write_offset; /* This is the offset in the usb data block to write the serial data -
- * it is different between devices
+ /* the last data state set - needed for doing
+ * a break
+ */
+ int write_offset; /* This is the offset in the usb data block to
+ * write the serial data - it varies between
+ * devices
*/
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
char prev_status, diff_status; /* Used for TIOCMIWAIT */
__u8 rx_flags; /* receive state flags (throttling) */
spinlock_t rx_lock; /* spinlock for receive state */
@@ -76,8 +83,10 @@ struct ftdi_private {
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
- speed_t force_baud; /* if non-zero, force the baud rate to this value */
- int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
+ speed_t force_baud; /* if non-zero, force the baud rate to
+ this value */
+ int force_rtscts; /* if non-zero, force RTS-CTS to always
+ be enabled */
spinlock_t tx_lock; /* spinlock for transmit state */
unsigned long tx_bytes;
@@ -88,13 +97,14 @@ struct ftdi_private {
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
int (*probe)(struct usb_serial *);
- void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
+ /* Special settings for probed ports. */
+ void (*port_probe)(struct ftdi_private *);
};
-static int ftdi_jtag_probe (struct usb_serial *serial);
-static int ftdi_mtxorb_hack_setup (struct usb_serial *serial);
-static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
-static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
+static int ftdi_jtag_probe(struct usb_serial *serial);
+static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
+static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
+static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
static struct ftdi_sio_quirk ftdi_jtag_quirk = {
.probe = ftdi_jtag_probe,
@@ -174,270 +184,270 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID),
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID),
.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) },
- { USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -642,7 +652,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver ftdi_driver = {
.name = "ftdi_sio",
@@ -678,30 +688,37 @@ static const char *ftdi_chip_name[] = {
| ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
/* function prototypes for a FTDI serial converter */
-static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static void ftdi_shutdown (struct usb_serial *serial);
-static int ftdi_sio_port_probe (struct usb_serial_port *port);
-static int ftdi_sio_port_remove (struct usb_serial_port *port);
-static int ftdi_open (struct usb_serial_port *port, struct file *filp);
-static void ftdi_close (struct usb_serial_port *port, struct file *filp);
-static int ftdi_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int ftdi_write_room (struct usb_serial_port *port);
-static int ftdi_chars_in_buffer (struct usb_serial_port *port);
-static void ftdi_write_bulk_callback (struct urb *urb);
-static void ftdi_read_bulk_callback (struct urb *urb);
-static void ftdi_process_read (struct work_struct *work);
-static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
-static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void ftdi_break_ctl (struct usb_serial_port *port, int break_state );
-static void ftdi_throttle (struct usb_serial_port *port);
-static void ftdi_unthrottle (struct usb_serial_port *port);
-
-static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
-static unsigned short int ftdi_232am_baud_to_divisor (int baud);
-static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
-static __u32 ftdi_232bm_baud_to_divisor (int baud);
+static int ftdi_sio_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static void ftdi_shutdown(struct usb_serial *serial);
+static int ftdi_sio_port_probe(struct usb_serial_port *port);
+static int ftdi_sio_port_remove(struct usb_serial_port *port);
+static int ftdi_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int ftdi_write_room(struct tty_struct *tty);
+static int ftdi_chars_in_buffer(struct tty_struct *tty);
+static void ftdi_write_bulk_callback(struct urb *urb);
+static void ftdi_read_bulk_callback(struct urb *urb);
+static void ftdi_process_read(struct work_struct *work);
+static void ftdi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int ftdi_tiocmget(struct tty_struct *tty, struct file *file);
+static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static void ftdi_throttle(struct tty_struct *tty);
+static void ftdi_unthrottle(struct tty_struct *tty);
+
+static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
+static unsigned short int ftdi_232am_baud_to_divisor(int baud);
+static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
+static __u32 ftdi_232bm_baud_to_divisor(int baud);
static struct usb_serial_driver ftdi_sio_device = {
.driver = {
@@ -752,44 +769,54 @@ static struct usb_serial_driver ftdi_sio_device = {
static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
{
unsigned short int divisor;
- int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
- if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
+ /* divisor shifted 3 bits to the left */
+ int divisor3 = base / 2 / baud;
+ if ((divisor3 & 0x7) == 7)
+ divisor3++; /* round x.7/8 up to x+1 */
divisor = divisor3 >> 3;
divisor3 &= 0x7;
- if (divisor3 == 1) divisor |= 0xc000; else // 0.125
- if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
- if (divisor3 != 0) divisor |= 0x8000; // 0.25
- if (divisor == 1) divisor = 0; /* special case for maximum baud rate */
+ if (divisor3 == 1)
+ divisor |= 0xc000;
+ else if (divisor3 >= 4)
+ divisor |= 0x4000;
+ else if (divisor3 != 0)
+ divisor |= 0x8000;
+ else if (divisor == 1)
+ divisor = 0; /* special case for maximum baud rate */
return divisor;
}
static unsigned short int ftdi_232am_baud_to_divisor(int baud)
{
- return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
+ return ftdi_232am_baud_base_to_divisor(baud, 48000000);
}
static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
{
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
__u32 divisor;
- int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+ /* divisor shifted 3 bits to the left */
+ int divisor3 = base / 2 / baud;
divisor = divisor3 >> 3;
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
/* Deal with special cases for highest baud rates. */
- if (divisor == 1) divisor = 0; else // 1.0
- if (divisor == 0x4001) divisor = 1; // 1.5
+ if (divisor == 1)
+ divisor = 0;
+ else if (divisor == 0x4001)
+ divisor = 1;
return divisor;
}
static __u32 ftdi_232bm_baud_to_divisor(int baud)
{
- return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
+ return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
}
#define set_mctrl(port, set) update_mctrl((port), (set), 0)
#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
-static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear)
+static int update_mctrl(struct usb_serial_port *port, unsigned int set,
+ unsigned int clear)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
char *buf;
@@ -843,42 +870,8 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned
}
-static __u32 get_ftdi_divisor(struct usb_serial_port * port);
-
-
-static int change_speed(struct usb_serial_port *port)
-{
- struct ftdi_private *priv = usb_get_serial_port_data(port);
- char *buf;
- __u16 urb_value;
- __u16 urb_index;
- __u32 urb_index_value;
- int rv;
-
- buf = kmalloc(1, GFP_NOIO);
- if (!buf)
- return -ENOMEM;
-
- urb_index_value = get_ftdi_divisor(port);
- urb_value = (__u16)urb_index_value;
- urb_index = (__u16)(urb_index_value >> 16);
- if (priv->interface) { /* FT2232C */
- urb_index = (__u16)((urb_index << 8) | priv->interface);
- }
-
- rv = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- FTDI_SIO_SET_BAUDRATE_REQUEST,
- FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
- urb_value, urb_index,
- buf, 0, WDR_SHORT_TIMEOUT);
-
- kfree(buf);
- return rv;
-}
-
-
-static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+static __u32 get_ftdi_divisor(struct tty_struct *tty,
+ struct usb_serial_port *port)
{ /* get_ftdi_divisor */
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u32 div_value = 0;
@@ -886,48 +879,56 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
int baud;
/*
- * The logic involved in setting the baudrate can be cleanly split in 3 steps.
- * Obtaining the actual baud rate is a little tricky since unix traditionally
- * somehow ignored the possibility to set non-standard baud rates.
+ * The logic involved in setting the baudrate can be cleanly split into
+ * 3 steps.
* 1. Standard baud rates are set in tty->termios->c_cflag
- * 2. If these are not enough, you can set any speed using alt_speed as follows:
+ * 2. If these are not enough, you can set any speed using alt_speed as
+ * follows:
* - set tty->termios->c_cflag speed to B38400
* - set your real speed in tty->alt_speed; it gets ignored when
* alt_speed==0, (or)
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
- * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
- * sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+ * follows:
+ * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP],
+ * this just sets alt_speed to (HI: 57600, VHI: 115200,
+ * SHI: 230400, WARP: 460800)
* ** Steps 1, 2 are done courtesy of tty_get_baud_rate
* 3. You can also set baud rate by setting custom divisor as follows
* - set tty->termios->c_cflag speed to B38400
- * - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+ * - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+ * follows:
* o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
* o custom_divisor set to baud_base / your_new_baudrate
- * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
- * spend some time and separate+move this common code to serial.c, it is
- * replicated in nearly every serial driver you see.
+ * ** Step 3 is done courtesy of code borrowed from serial.c
+ * I should really spend some time and separate + move this common
+ * code to serial.c, it is replicated in nearly every serial driver
+ * you see.
*/
- /* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+ /* 1. Get the baud rate from the tty settings, this observes
+ alt_speed hack */
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
- /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+ /* 2. Observe async-compatible custom_divisor hack, update baudrate
+ if needed */
if (baud == 38400 &&
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(priv->custom_divisor)) {
baud = priv->baud_base / priv->custom_divisor;
- dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
+ dbg("%s - custom divisor %d sets baud rate to %d",
+ __func__, priv->custom_divisor, baud);
}
/* 3. Convert baudrate to device-specific divisor */
- if (!baud) baud = 9600;
- switch(priv->chip_type) {
+ if (!baud)
+ baud = 9600;
+ switch (priv->chip_type) {
case SIO: /* SIO chip */
- switch(baud) {
+ switch (baud) {
case 300: div_value = ftdi_sio_b300; break;
case 600: div_value = ftdi_sio_b600; break;
case 1200: div_value = ftdi_sio_b1200; break;
@@ -940,7 +941,8 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
case 115200: div_value = ftdi_sio_b115200; break;
} /* baud */
if (div_value == 0) {
- dbg("%s - Baudrate (%d) requested is not supported", __func__, baud);
+ dbg("%s - Baudrate (%d) requested is not supported",
+ __func__, baud);
div_value = ftdi_sio_b9600;
baud = 9600;
div_okay = 0;
@@ -950,7 +952,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (baud <= 3000000) {
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dbg("%s - Baud rate too high!", __func__);
baud = 9600;
div_value = ftdi_232am_baud_to_divisor(9600);
div_okay = 0;
@@ -962,7 +964,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (baud <= 3000000) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
- dbg("%s - Baud rate too high!", __func__);
+ dbg("%s - Baud rate too high!", __func__);
div_value = ftdi_232bm_baud_to_divisor(9600);
div_okay = 0;
baud = 9600;
@@ -976,12 +978,45 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
ftdi_chip_name[priv->chip_type]);
}
- tty_encode_baud_rate(port->tty, baud, baud);
- return(div_value);
+ tty_encode_baud_rate(tty, baud, baud);
+ return div_value;
+}
+
+static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ char *buf;
+ __u16 urb_value;
+ __u16 urb_index;
+ __u32 urb_index_value;
+ int rv;
+
+ buf = kmalloc(1, GFP_NOIO);
+ if (!buf)
+ return -ENOMEM;
+
+ urb_index_value = get_ftdi_divisor(tty, port);
+ urb_value = (__u16)urb_index_value;
+ urb_index = (__u16)(urb_index_value >> 16);
+ if (priv->interface) { /* FT2232C */
+ urb_index = (__u16)((urb_index << 8) | priv->interface);
+ }
+
+ rv = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_BAUDRATE_REQUEST,
+ FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+ urb_value, urb_index,
+ buf, 0, WDR_SHORT_TIMEOUT);
+
+ kfree(buf);
+ return rv;
}
-static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo)
+
+static int get_serial_info(struct usb_serial_port *port,
+ struct serial_struct __user *retinfo)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct tmp;
@@ -998,7 +1033,8 @@ static int get_serial_info(struct usb_serial_port * port, struct serial_struct _
} /* get_serial_info */
-static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo)
+static int set_serial_info(struct tty_struct *tty,
+ struct usb_serial_port *port, struct serial_struct __user *newinfo)
{ /* set_serial_info */
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct serial_struct new_serial;
@@ -1006,7 +1042,7 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
return -EFAULT;
- old_priv = * priv;
+ old_priv = *priv;
/* Do error checking and permission checking */
@@ -1027,33 +1063,32 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _
/* Make the changes - these are privileged changes! */
priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
- (new_serial.flags & ASYNC_FLAGS));
+ (new_serial.flags & ASYNC_FLAGS));
priv->custom_divisor = new_serial.custom_divisor;
- port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if ((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) {
if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- port->tty->alt_speed = 57600;
+ tty->alt_speed = 57600;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- port->tty->alt_speed = 115200;
+ tty->alt_speed = 115200;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- port->tty->alt_speed = 230400;
+ tty->alt_speed = 230400;
else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- port->tty->alt_speed = 460800;
+ tty->alt_speed = 460800;
else
- port->tty->alt_speed = 0;
+ tty->alt_speed = 0;
}
if (((old_priv.flags & ASYNC_SPD_MASK) !=
(priv->flags & ASYNC_SPD_MASK)) ||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(old_priv.custom_divisor != priv->custom_divisor))) {
- change_speed(port);
+ change_speed(tty, port);
}
-
- return (0);
+ return 0;
} /* set_serial_info */
@@ -1082,11 +1117,10 @@ static void ftdi_determine_type(struct usb_serial_port *port)
priv->chip_type = FT2232C;
/* Determine interface code. */
inter = serial->interface->altsetting->desc.bInterfaceNumber;
- if (inter == 0) {
+ if (inter == 0)
priv->interface = PIT_SIOA;
- } else {
+ else
priv->interface = PIT_SIOB;
- }
/* BM-type devices have a bug where bcdDevice gets set
* to 0x200 when iSerialNumber is 0. */
if (version < 0x500) {
@@ -1120,7 +1154,8 @@ static void ftdi_determine_type(struct usb_serial_port *port)
* ***************************************************************************
*/
-static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_latency_timer(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1129,14 +1164,14 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
int rv = 0;
- dbg("%s",__func__);
+ dbg("%s", __func__);
rv = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0),
FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
0, priv->interface,
- (char*) &latency, 1, WDR_TIMEOUT);
+ (char *) &latency, 1, WDR_TIMEOUT);
if (rv < 0) {
dev_err(dev, "Unable to read latency timer: %i\n", rv);
@@ -1146,8 +1181,9 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a
}
/* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
- size_t count)
+static ssize_t store_latency_timer(struct device *dev,
+ struct device_attribute *attr, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1175,8 +1211,8 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute *
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
-static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
- size_t count)
+static ssize_t store_event_char(struct device *dev,
+ struct device_attribute *attr, const char *valbuf, size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1202,7 +1238,8 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
return count;
}
-static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer,
+ store_latency_timer);
static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
static int create_sysfs_attrs(struct usb_serial_port *port)
@@ -1210,7 +1247,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
int retval = 0;
- dbg("%s",__func__);
+ dbg("%s", __func__);
/* XXX I've no idea if the original SIO supports the event_char
* sysfs parameter, so I'm playing it safe. */
@@ -1232,7 +1269,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- dbg("%s",__func__);
+ dbg("%s", __func__);
/* XXX see create_sysfs_attrs */
if (priv->chip_type != SIO) {
@@ -1253,9 +1290,11 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
*/
/* Probe function to check for special devices */
-static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int ftdi_sio_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
- struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info;
+ struct ftdi_sio_quirk *quirk =
+ (struct ftdi_sio_quirk *)id->driver_info;
if (quirk && quirk->probe) {
int ret = quirk->probe(serial);
@@ -1274,17 +1313,18 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
- if (!priv){
- err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
+ if (!priv) {
+ err("%s- kmalloc(%Zd) failed.", __func__,
+ sizeof(struct ftdi_private));
return -ENOMEM;
}
spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
+ init_waitqueue_head(&priv->delta_msr_wait);
/* This will push the characters through immediately rather
than queue a task to deliver them */
priv->flags = ASYNC_LOW_LATENCY;
@@ -1294,9 +1334,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Increase the size of read buffers */
kfree(port->bulk_in_buffer);
- port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
+ port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL);
if (!port->bulk_in_buffer) {
- kfree (priv);
+ kfree(priv);
return -ENOMEM;
}
if (port->read_urb) {
@@ -1309,7 +1349,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
- usb_free_urb (port->write_urb);
+ usb_free_urb(port->write_urb);
port->write_urb = NULL;
}
kfree(port->bulk_out_buffer);
@@ -1317,7 +1357,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, priv);
- ftdi_determine_type (port);
+ ftdi_determine_type(port);
create_sysfs_attrs(port);
return 0;
}
@@ -1325,9 +1365,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
/* Setup for the USB-UIRT device, which requires hardwired
* baudrate (38400 gets mapped to 312500) */
/* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
{
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
@@ -1336,9 +1376,10 @@ static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
/* Setup for the HE-TIRA1 device, which requires hardwired
* baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
-static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
+
+static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
{
- dbg("%s",__func__);
+ dbg("%s", __func__);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
@@ -1356,7 +1397,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
- dbg("%s",__func__);
+ dbg("%s", __func__);
if (interface == udev->actconfig->interface[0]) {
info("Ignoring serial port reserved for JTAG");
@@ -1390,7 +1431,7 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
* calls __serial_close for each open of the port
* shutdown is called then (ie ftdi_shutdown)
*/
-static void ftdi_shutdown (struct usb_serial *serial)
+static void ftdi_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
}
@@ -1404,7 +1445,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
remove_sysfs_attrs(port);
/* all open ports are closed at this point
- * (by usbserial.c:__serial_close, which calls ftdi_close)
+ * (by usbserial.c:__serial_close, which calls ftdi_close)
*/
if (priv) {
@@ -1415,7 +1456,8 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
return 0;
}
-static int ftdi_open (struct usb_serial_port *port, struct file *filp)
+static int ftdi_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{ /* ftdi_open */
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1433,8 +1475,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
priv->rx_bytes = 0;
spin_unlock_irqrestore(&priv->rx_lock, flags);
- if (port->tty)
- port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ if (tty)
+ tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
/* No error checking for this (will get errors later anyway) */
/* See ftdi_sio.h for description of what is reset */
@@ -1448,8 +1490,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (port->tty)
- ftdi_set_termios(port, port->tty->termios);
+ if (tty)
+ ftdi_set_termios(tty, port, tty->termios);
/* FIXME: Flow control might be enabled, so it should be checked -
we have no control of defaults! */
@@ -1464,12 +1506,14 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, dev,
- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ftdi_read_bulk_callback, port);
+ usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d", __func__, result);
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
return result;
@@ -1485,16 +1529,17 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
*
*/
-static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{ /* ftdi_close */
- unsigned int c_cflag = port->tty->termios->c_cflag;
+ unsigned int c_cflag = tty->termios->c_cflag;
struct ftdi_private *priv = usb_get_serial_port_data(port);
char buf[1];
dbg("%s", __func__);
mutex_lock(&port->serial->disc_mutex);
- if (c_cflag & HUPCL && !port->serial->disconnected){
+ if (c_cflag & HUPCL && !port->serial->disconnected) {
/* Disable flow control */
if (usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
@@ -1527,7 +1572,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
*
* The new devices do not require this byte
*/
-static int ftdi_write (struct usb_serial_port *port,
+static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{ /* ftdi_write */
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1554,7 +1599,7 @@ static int ftdi_write (struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->tx_lock, flags);
data_offset = priv->write_offset;
- dbg("data_offset set to %d",data_offset);
+ dbg("data_offset set to %d", data_offset);
/* Determine total transfer size */
transfer_size = count;
@@ -1565,7 +1610,7 @@ static int ftdi_write (struct usb_serial_port *port,
(PKTSZ - data_offset)));
}
- buffer = kmalloc (transfer_size, GFP_ATOMIC);
+ buffer = kmalloc(transfer_size, GFP_ATOMIC);
if (!buffer) {
err("%s ran out of kernel memory for urb ...", __func__);
count = -ENOMEM;
@@ -1581,20 +1626,20 @@ static int ftdi_write (struct usb_serial_port *port,
/* Copy data */
if (data_offset > 0) {
- /* Original sio requires control byte at start of each packet. */
+ /* Original sio requires control byte at start of
+ each packet. */
int user_pktsz = PKTSZ - data_offset;
int todo = count;
unsigned char *first_byte = buffer;
const unsigned char *current_position = buf;
while (todo > 0) {
- if (user_pktsz > todo) {
+ if (user_pktsz > todo)
user_pktsz = todo;
- }
/* Write the control byte at the front of the packet*/
*first_byte = 1 | ((user_pktsz) << 2);
/* Copy data for packet */
- memcpy (first_byte + data_offset,
+ memcpy(first_byte + data_offset,
current_position, user_pktsz);
first_byte += user_pktsz + data_offset;
current_position += user_pktsz;
@@ -1603,20 +1648,23 @@ static int ftdi_write (struct usb_serial_port *port,
} else {
/* No control byte required. */
/* Copy in the data to send */
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
}
- usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ transfer_size, buffer);
/* fill the buffer and send it */
usb_fill_bulk_urb(urb, port->serial->dev,
- usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
- buffer, transfer_size,
- ftdi_write_bulk_callback, port);
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ buffer, transfer_size,
+ ftdi_write_bulk_callback, port);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - failed submitting write urb, error %d", __func__, status);
+ err("%s - failed submitting write urb, error %d",
+ __func__, status);
count = status;
goto error;
} else {
@@ -1635,7 +1683,7 @@ static int ftdi_write (struct usb_serial_port *port,
error:
usb_free_urb(urb);
error_no_urb:
- kfree (buffer);
+ kfree(buffer);
error_no_buffer:
spin_lock_irqsave(&priv->tx_lock, flags);
priv->tx_outstanding_urbs--;
@@ -1646,7 +1694,7 @@ error_no_buffer:
/* This function may get called when the device is closed */
-static void ftdi_write_bulk_callback (struct urb *urb)
+static void ftdi_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
@@ -1656,7 +1704,7 @@ static void ftdi_write_bulk_callback (struct urb *urb)
int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
dbg("%s - port %d", __func__, port->number);
@@ -1686,8 +1734,9 @@ static void ftdi_write_bulk_callback (struct urb *urb)
} /* ftdi_write_bulk_callback */
-static int ftdi_write_room( struct usb_serial_port *port )
+static int ftdi_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int room;
unsigned long flags;
@@ -1707,11 +1756,11 @@ static int ftdi_write_room( struct usb_serial_port *port )
}
spin_unlock_irqrestore(&priv->tx_lock, flags);
return room;
-} /* ftdi_write_room */
-
+}
-static int ftdi_chars_in_buffer (struct usb_serial_port *port)
-{ /* ftdi_chars_in_buffer */
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int buffered;
unsigned long flags;
@@ -1726,12 +1775,10 @@ static int ftdi_chars_in_buffer (struct usb_serial_port *port)
buffered = 0;
}
return buffered;
-} /* ftdi_chars_in_buffer */
-
-
+}
-static void ftdi_read_bulk_callback (struct urb *urb)
-{ /* ftdi_read_bulk_callback */
+static void ftdi_read_bulk_callback(struct urb *urb)
+{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
struct ftdi_private *priv;
@@ -1740,19 +1787,21 @@ static void ftdi_read_bulk_callback (struct urb *urb)
int status = urb->status;
if (urb->number_of_packets > 0) {
- err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
- urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
- err("%s transfer_flags %x ", __func__,urb->transfer_flags );
+ err("%s transfer_buffer_length %d actual_length %d number of packets %d",
+ __func__,
+ urb->transfer_buffer_length,
+ urb->actual_length, urb->number_of_packets);
+ err("%s transfer_flags %x ", __func__, urb->transfer_flags);
}
dbg("%s - port %d", __func__, port->number);
- if (port->open_count <= 0)
+ if (port->port.count <= 0)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
- dbg("%s - bad tty pointer - exiting",__func__);
+ dbg("%s - bad tty pointer - exiting", __func__);
return;
}
@@ -1762,14 +1811,13 @@ static void ftdi_read_bulk_callback (struct urb *urb)
return;
}
- if (urb != port->read_urb) {
+ if (urb != port->read_urb)
err("%s - Not my urb!", __func__);
- }
if (status) {
- /* This will happen at close every time so it is a dbg not an err */
- dbg("(this is ok on close) nonzero read bulk status received: "
- "%d", status);
+ /* This will happen at close every time so it is a dbg not an
+ err */
+ dbg("(this is ok on close) nonzero read bulk status received: %d", status);
return;
}
@@ -1785,7 +1833,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
} /* ftdi_read_bulk_callback */
-static void ftdi_process_read (struct work_struct *work)
+static void ftdi_process_read(struct work_struct *work)
{ /* ftdi_process_read */
struct ftdi_private *priv =
container_of(work, struct ftdi_private, rx_work.work);
@@ -1803,12 +1851,12 @@ static void ftdi_process_read (struct work_struct *work)
dbg("%s - port %d", __func__, port->number);
- if (port->open_count <= 0)
+ if (port->port.count <= 0)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty) {
- dbg("%s - bad tty pointer - exiting",__func__);
+ dbg("%s - bad tty pointer - exiting", __func__);
return;
}
@@ -1832,11 +1880,11 @@ static void ftdi_process_read (struct work_struct *work)
urb->actual_length - priv->rx_processed);
} else {
/* The first two bytes of every read packet are status */
- if (urb->actual_length > 2) {
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
- } else {
- dbg("Status only: %03oo %03oo",data[0],data[1]);
- }
+ if (urb->actual_length > 2)
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ else
+ dbg("Status only: %03oo %03oo", data[0], data[1]);
}
@@ -1846,16 +1894,19 @@ static void ftdi_process_read (struct work_struct *work)
/* if CD is dropped and the line is not CLOCAL then we should hangup */
need_flip = 0;
- for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ for (packet_offset = priv->rx_processed;
+ packet_offset < urb->actual_length; packet_offset += PKTSZ) {
int length;
- /* Compare new line status to the old one, signal if different */
- /* N.B. packet may be processed more than once, but differences
- * are only processed once. */
+ /* Compare new line status to the old one, signal if different/
+ N.B. packet may be processed more than once, but differences
+ are only processed once. */
if (priv != NULL) {
- char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
+ char new_status = data[packet_offset + 0] &
+ FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
- priv->diff_status |= new_status ^ priv->prev_status;
+ priv->diff_status |=
+ new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
@@ -1872,30 +1923,31 @@ static void ftdi_process_read (struct work_struct *work)
break;
}
if (tty_buffer_request_room(tty, length) < length) {
- /* break out & wait for throttling/unthrottling to happen */
+ /* break out & wait for throttling/unthrottling to
+ happen */
dbg("%s - receive room low", __func__);
break;
}
/* Handle errors and break */
error_flag = TTY_NORMAL;
- /* Although the device uses a bitmask and hence can have multiple */
- /* errors on a packet - the order here sets the priority the */
- /* error is returned to the tty layer */
+ /* Although the device uses a bitmask and hence can have
+ multiple errors on a packet - the order here sets the
+ priority the error is returned to the tty layer */
- if ( data[packet_offset+1] & FTDI_RS_OE ) {
+ if (data[packet_offset+1] & FTDI_RS_OE) {
error_flag = TTY_OVERRUN;
dbg("OVERRRUN error");
}
- if ( data[packet_offset+1] & FTDI_RS_BI ) {
+ if (data[packet_offset+1] & FTDI_RS_BI) {
error_flag = TTY_BREAK;
dbg("BREAK received");
}
- if ( data[packet_offset+1] & FTDI_RS_PE ) {
+ if (data[packet_offset+1] & FTDI_RS_PE) {
error_flag = TTY_PARITY;
dbg("PARITY error");
}
- if ( data[packet_offset+1] & FTDI_RS_FE ) {
+ if (data[packet_offset+1] & FTDI_RS_FE) {
error_flag = TTY_FRAME;
dbg("FRAMING error");
}
@@ -1904,7 +1956,8 @@ static void ftdi_process_read (struct work_struct *work)
/* Note that the error flag is duplicated for
every character received since we don't know
which character it applied to */
- tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
+ tty_insert_flip_char(tty,
+ data[packet_offset + i], error_flag);
}
need_flip = 1;
}
@@ -1912,19 +1965,19 @@ static void ftdi_process_read (struct work_struct *work)
#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
/* if a parity error is detected you get status packets forever
until a character is sent without a parity error.
- This doesn't work well since the application receives a never
- ending stream of bad data - even though new data hasn't been sent.
- Therefore I (bill) have taken this out.
+ This doesn't work well since the application receives a
+ never ending stream of bad data - even though new data
+ hasn't been sent. Therefore I (bill) have taken this out.
However - this might make sense for framing errors and so on
so I am leaving the code in for now.
*/
else {
- if (error_flag != TTY_NORMAL){
+ if (error_flag != TTY_NORMAL) {
dbg("error_flag is not normal");
- /* In this case it is just status - if that is an error send a bad character */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ /* In this case it is just status - if that is
+ an error send a bad character */
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
tty_flip_buffer_push(tty);
- }
tty_insert_flip_char(tty, 0xff, error_flag);
need_flip = 1;
}
@@ -1933,9 +1986,8 @@ static void ftdi_process_read (struct work_struct *work)
} /* "for(packet_offset=0..." */
/* Low latency */
- if (need_flip) {
+ if (need_flip)
tty_flip_buffer_push(tty);
- }
if (packet_offset < urb->actual_length) {
/* not completely processed - record progress */
@@ -1954,12 +2006,11 @@ static void ftdi_process_read (struct work_struct *work)
}
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* if the port is closed stop trying to read */
- if (port->open_count > 0){
+ if (port->port.count > 0)
/* delay processing of remainder */
schedule_delayed_work(&priv->rx_work, 1);
- } else {
+ else
dbg("%s - port is closed", __func__);
- }
return;
}
@@ -1967,24 +2018,26 @@ static void ftdi_process_read (struct work_struct *work)
priv->rx_processed = 0;
/* if the port is closed stop trying to read */
- if (port->open_count > 0){
+ if (port->port.count > 0) {
/* Continue trying to always read */
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ftdi_read_bulk_callback, port);
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ftdi_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
}
-
- return;
} /* ftdi_process_read */
-static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value = 0;
char buf[1];
@@ -1993,22 +2046,23 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
/* see drivers/char/tty_io.c to see it used */
/* last_set_data_urb_value NEVER has the break bit set in it */
- if (break_state) {
+ if (break_state)
urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
- } else {
+ else
urb_value = priv->last_set_data_urb_value;
- }
-
- if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
- FTDI_SIO_SET_DATA_REQUEST,
- FTDI_SIO_SET_DATA_REQUEST_TYPE,
- urb_value , priv->interface,
- buf, 0, WDR_TIMEOUT) < 0) {
- err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
+ if (usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_SET_DATA_REQUEST,
+ FTDI_SIO_SET_DATA_REQUEST_TYPE,
+ urb_value , priv->interface,
+ buf, 0, WDR_TIMEOUT) < 0) {
+ err("%s FAILED to enable/disable break state (state was %d)",
+ __func__, break_state);
}
- dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
+ dbg("%s break state is %d - urb is %d", __func__,
+ break_state, urb_value);
}
@@ -2018,26 +2072,28 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
* WARNING: set_termios calls this with old_termios in kernel space
*/
-static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void ftdi_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{ /* ftdi_termios */
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
- // Added for xon/xoff support
+ /* Added for xon/xoff support */
unsigned int iflag = termios->c_iflag;
unsigned char vstop;
unsigned char vstart;
dbg("%s", __func__);
- /* Force baud rate if this device requires it, unless it is set to B0. */
+ /* Force baud rate if this device requires it, unless it is set to
+ B0. */
if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
dbg("%s: forcing baud rate for this device", __func__);
- tty_encode_baud_rate(port->tty, priv->force_baud,
+ tty_encode_baud_rate(tty, priv->force_baud,
priv->force_baud);
}
@@ -2053,8 +2109,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
not - so just do the change regardless - should be able to
compare old_termios and tty->termios */
/* NOTE These routines can get interrupted by
- ftdi_sio_read_bulk_callback - need to examine what this
- means - don't see any problems yet */
+ ftdi_sio_read_bulk_callback - need to examine what this means -
+ don't see any problems yet */
/* Set number of data bits, parity, stop bits */
@@ -2078,8 +2134,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
}
- /* This is needed by the break command since it uses the same command - but is
- * or'ed with this value */
+ /* This is needed by the break command since it uses the same command
+ - but is or'ed with this value */
priv->last_set_data_urb_value = urb_value;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2091,7 +2147,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
/* Now do the baudrate */
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
/* Disable flow control */
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -2104,13 +2160,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} else {
/* set the baudrate determined before */
- if (change_speed(port)) {
+ if (change_speed(tty, port))
err("%s urb failed to set baudrate", __func__);
- }
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
- if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+ if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
- }
}
/* Set flow control */
@@ -2130,18 +2184,22 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
/*
* Xon/Xoff code
*
- * Check the IXOFF status in the iflag component of the termios structure
- * if IXOFF is not set, the pre-xon/xoff code is executed.
- */
+ * Check the IXOFF status in the iflag component of the
+ * termios structure. If IXOFF is not set, the pre-xon/xoff
+ * code is executed.
+ */
if (iflag & IXOFF) {
- dbg("%s request to enable xonxoff iflag=%04x",__func__,iflag);
- // Try to enable the XON/XOFF on the ftdi_sio
- // Set the vstart and vstop -- could have been done up above where
- // a lot of other dereferencing is done but that would be very
- // inefficient as vstart and vstop are not always needed
+ dbg("%s request to enable xonxoff iflag=%04x",
+ __func__, iflag);
+ /* Try to enable the XON/XOFF on the ftdi_sio
+ * Set the vstart and vstop -- could have been done up
+ * above where a lot of other dereferencing is done but
+ * that would be very inefficient as vstart and vstop
+ * are not always needed.
+ */
vstart = termios->c_cc[VSTART];
vstop = termios->c_cc[VSTOP];
- urb_value=(vstop << 8) | (vstart);
+ urb_value = (vstop << 8) | (vstart);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
@@ -2153,8 +2211,9 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
err("urb failed to set to xon/xoff flow control");
}
} else {
- /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
- /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+ /* else clause to only run if cflag ! CRTSCTS and iflag
+ * ! XOFF. CHECKME Assuming XON/XOFF handled by tty
+ * stack - not by device */
dbg("%s Turning off hardware flow control", __func__);
if (usb_control_msg(dev,
usb_sndctrlpipe(dev, 0),
@@ -2168,11 +2227,11 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old
}
return;
-} /* ftdi_termios */
-
+}
-static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned char buf[2];
int ret;
@@ -2181,32 +2240,35 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
switch (priv->chip_type) {
case SIO:
/* Request the status from the device */
- if ((ret = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, 0,
- buf, 1, WDR_TIMEOUT)) < 0 ) {
+ ret = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, 0,
+ buf, 1, WDR_TIMEOUT);
+ if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __func__,
ret);
- return(ret);
+ return ret;
}
break;
case FT8U232AM:
case FT232BM:
case FT2232C:
case FT232RL:
- /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
- format as the data returned from the in point */
- if ((ret = usb_control_msg(port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- FTDI_SIO_GET_MODEM_STATUS_REQUEST,
- FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
- 0, priv->interface,
- buf, 2, WDR_TIMEOUT)) < 0 ) {
+ /* the 8U232AM returns a two byte value (the sio is a 1 byte
+ value) - in the same format as the data returned from the in
+ point */
+ ret = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+ 0, priv->interface,
+ buf, 2, WDR_TIMEOUT);
+ if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __func__,
ret);
- return(ret);
+ return ret;
}
break;
default:
@@ -2221,15 +2283,19 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
priv->last_dtr_rts;
}
-static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s TIOCMSET", __func__);
return update_mctrl(port, set, clear);
}
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
dbg("%s cmd 0x%04x", __func__, cmd);
@@ -2238,10 +2304,12 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
switch (cmd) {
case TIOCGSERIAL: /* gets serial port data */
- return get_serial_info(port, (struct serial_struct __user *) arg);
+ return get_serial_info(port,
+ (struct serial_struct __user *) arg);
case TIOCSSERIAL: /* sets serial port data */
- return set_serial_info(port, (struct serial_struct __user *) arg);
+ return set_serial_info(tty, port,
+ (struct serial_struct __user *) arg);
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
@@ -2260,45 +2328,41 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne
else {
char diff = priv->diff_status;
- if (diff == 0) {
+ if (diff == 0)
return -EIO; /* no change => error */
- }
/* Consume all events */
priv->diff_status = 0;
- /* Return 0 if caller wanted to know about these bits */
- if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
- ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
- ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
- ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+ /* Return 0 if caller wanted to know about
+ these bits */
+ if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+ ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+ ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) ||
+ ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) {
return 0;
}
/*
- * Otherwise caller can't care less about what happened,
- * and so we continue to wait for more events.
+ * Otherwise caller can't care less about what
+ * happened,and so we continue to wait for more
+ * events.
*/
}
}
- return(0);
- break;
+ return 0;
default:
break;
-
}
-
-
- /* This is not necessarily an error - turns out the higher layers will do
- * some ioctls itself (see comment above)
+ /* This is not necessarily an error - turns out the higher layers
+ * will do some ioctls themselves (see comment above)
*/
dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
+ return -ENOIOCTLCMD;
+}
- return(-ENOIOCTLCMD);
-} /* ftdi_ioctl */
-
-
-static void ftdi_throttle (struct usb_serial_port *port)
+static void ftdi_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -2310,8 +2374,9 @@ static void ftdi_throttle (struct usb_serial_port *port)
}
-static void ftdi_unthrottle (struct usb_serial_port *port)
+static void ftdi_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
@@ -2327,7 +2392,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
schedule_delayed_work(&priv->rx_work, 0);
}
-static int __init ftdi_init (void)
+static int __init ftdi_init(void)
{
int retval;
@@ -2357,13 +2422,13 @@ failed_sio_register:
}
-static void __exit ftdi_exit (void)
+static void __exit ftdi_exit(void)
{
dbg("%s", __func__);
- usb_deregister (&ftdi_driver);
- usb_serial_deregister (&ftdi_sio_device);
+ usb_deregister(&ftdi_driver);
+ usb_serial_deregister(&ftdi_sio_device);
}
@@ -2371,8 +2436,8 @@ static void __exit ftdi_exit (void)
module_init(ftdi_init);
module_exit(ftdi_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8302eca893e..a577ea44dcf 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -1,20 +1,20 @@
/*
- * Definitions for the FTDI USB Single Port Serial Converter -
- * known as FTDI_SIO (Serial Input/Output application of the chipset)
+ * Definitions for the FTDI USB Single Port Serial Converter -
+ * known as FTDI_SIO (Serial Input/Output application of the chipset)
*
* The example I have is known as the USC-1000 which is available from
* http://www.dse.co.nz - cat no XH4214 It looks similar to this:
* http://www.dansdata.com/usbser.htm but I can't be sure There are other
* USC-1000s which don't look like my device though so beware!
*
- * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
+ * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
* USB on the other.
*
* Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
* of the protocol required to talk to the device and ongoing assistence
* during development.
*
- * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
+ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
* FTDI_SIO implementation.
*
* Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
@@ -472,7 +472,7 @@
/*
* DSS-20 Sync Station for Sony Ericsson P800
*/
-#define FTDI_DSS20_PID 0xFC82
+#define FTDI_DSS20_PID 0xFC82
/*
* Home Electronics (www.home-electro.com) USB gadgets
@@ -884,7 +884,7 @@
/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_RESET
- * wValue: Control Value
+ * wValue: Control Value
* 0 = Reset SIO
* 1 = Purge RX buffer
* 2 = Purge TX buffer
@@ -952,7 +952,7 @@
* 101 - add .625 to divisor
* 110 - add .750 to divisor
* 111 - add .875 to divisor
- * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is
+ * Bits 15 to 0 of the 17-bit divisor are placed in the urb value. Bit 16 is
* placed in bit 0 of the urb index.
*
* Note that there are a couple of special cases to support the highest baud
@@ -971,8 +971,8 @@ typedef enum {
} ftdi_chip_type_t;
typedef enum {
- ftdi_sio_b300 = 0,
- ftdi_sio_b600 = 1,
+ ftdi_sio_b300 = 0,
+ ftdi_sio_b600 = 1,
ftdi_sio_b1200 = 2,
ftdi_sio_b2400 = 3,
ftdi_sio_b4800 = 4,
@@ -981,7 +981,7 @@ typedef enum {
ftdi_sio_b38400 = 7,
ftdi_sio_b57600 = 8,
ftdi_sio_b115200 = 9
-} FTDI_SIO_baudrate_t ;
+} FTDI_SIO_baudrate_t;
/*
* The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values
@@ -990,19 +990,19 @@ typedef enum {
#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
#define FTDI_SIO_SET_BREAK (0x1 << 14)
/* FTDI_SIO_SET_DATA */
/*
- * BmRequestType: 0100 0000B
+ * BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_SET_DATA
* wValue: Data characteristics (see below)
* wIndex: Port
@@ -1035,7 +1035,7 @@ typedef enum {
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
-/*
+/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_MODEM_CTRL
* wValue: ControlValue (see below)
@@ -1049,11 +1049,11 @@ typedef enum {
*/
#define FTDI_SIO_SET_DTR_MASK 0x1
-#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8))
-#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_HIGH (1 | (FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_LOW (0 | (FTDI_SIO_SET_DTR_MASK << 8))
#define FTDI_SIO_SET_RTS_MASK 0x2
-#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
-#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_HIGH (2 | (FTDI_SIO_SET_RTS_MASK << 8))
+#define FTDI_SIO_SET_RTS_LOW (0 | (FTDI_SIO_SET_RTS_MASK << 8))
/*
* ControlValue
@@ -1076,7 +1076,7 @@ typedef enum {
/* FTDI_SIO_SET_FLOW_CTRL */
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
-#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
@@ -1085,7 +1085,7 @@ typedef enum {
* bRequest: FTDI_SIO_SET_FLOW_CTRL
* wValue: Xoff/Xon
* wIndex: Protocol/Port - hIndex is protocl / lIndex is port
- * wLength: 0
+ * wLength: 0
* Data: None
*
* hIndex protocol is:
@@ -1101,10 +1101,10 @@ typedef enum {
*
* A value of zero in the hIndex field disables handshaking
*
- * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character
+ * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character
* and the lValue field contains the XON character.
- */
-
+ */
+
/*
* FTDI_SIO_GET_LATENCY_TIMER
*
@@ -1118,7 +1118,7 @@ typedef enum {
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
-/*
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_SIO_GET_LATENCY_TIMER
* wValue: 0
@@ -1127,7 +1127,7 @@ typedef enum {
* Data: latency (on return)
*/
-/*
+/*
* FTDI_SIO_SET_LATENCY_TIMER
*
* Set the timeout interval. The FTDI collects data from the slave
@@ -1140,7 +1140,7 @@ typedef enum {
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_LATENCY_TIMER
* wValue: Latency (milliseconds)
@@ -1155,7 +1155,7 @@ typedef enum {
*/
/*
- * FTDI_SIO_SET_EVENT_CHAR
+ * FTDI_SIO_SET_EVENT_CHAR
*
* Set the special event character for the specified communications port.
* If the device sees this character it will immediately return the
@@ -1168,7 +1168,7 @@ typedef enum {
#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_EVENT_CHAR
* wValue: EventChar
@@ -1184,12 +1184,12 @@ typedef enum {
* B9..15 Reserved
*
*/
-
+
/* FTDI_SIO_SET_ERROR_CHAR */
/* Set the parity error replacement character for the specified communications port */
-/*
+/*
* BmRequestType: 0100 0000b
* bRequest: FTDI_SIO_SET_EVENT_CHAR
* wValue: Error Char
@@ -1215,15 +1215,15 @@ typedef enum {
#define FTDI_SIO_DSR_MASK 0x20
#define FTDI_SIO_RI_MASK 0x40
#define FTDI_SIO_RLSD_MASK 0x80
-/*
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_SIO_GET_MODEM_STATUS
* wValue: zero
* wIndex: Port
* wLength: 1
* Data: Status
- *
- * One byte of data is returned
+ *
+ * One byte of data is returned
* B0..3 0
* B4 CTS
* 0 = inactive
@@ -1236,15 +1236,15 @@ typedef enum {
* 1 = active
* B7 Receive Line Signal Detect (RLSD)
* 0 = inactive
- * 1 = active
+ * 1 = active
*/
-/* Descriptors returned by the device
- *
+/* Descriptors returned by the device
+ *
* Device Descriptor
- *
+ *
* Offset Field Size Value Description
* 0 bLength 1 0x12 Size of descriptor in bytes
* 1 bDescriptorType 1 0x01 DEVICE Descriptor Type
@@ -1260,9 +1260,9 @@ typedef enum {
* 15 iProduct 1 0x02 Index of prod string desc
* 16 iSerialNumber 1 0x02 Index of serial nmr string desc
* 17 bNumConfigurations 1 0x01 Number of possible configurations
- *
+ *
* Configuration Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x09 Size of descriptor in bytes
* 1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type
@@ -1272,9 +1272,9 @@ typedef enum {
* 6 iConfiguration 1 0x02 Index of config string descriptor
* 7 bmAttributes 1 0x20 Config characteristics Remote Wakeup
* 8 MaxPower 1 0x1E Max power consumption
- *
+ *
* Interface Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x09 Size of descriptor in bytes
* 1 bDescriptorType 1 0x04 INTERFACE Descriptor Type
@@ -1285,9 +1285,9 @@ typedef enum {
* 6 bInterfaceSubClass 1 0xFF Subclass Code
* 7 bInterfaceProtocol 1 0xFF Protocol Code
* 8 iInterface 1 0x02 Index of interface string description
- *
+ *
* IN Endpoint Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x07 Size of descriptor in bytes
* 1 bDescriptorType 1 0x05 ENDPOINT descriptor type
@@ -1295,9 +1295,9 @@ typedef enum {
* 3 bmAttributes 1 0x02 Endpoint attributes - Bulk
* 4 bNumEndpoints 2 0x0040 maximum packet size
* 5 bInterval 1 0x00 Interval for polling endpoint
- *
+ *
* OUT Endpoint Descriptor
- *
+ *
* Offset Field Size Value
* 0 bLength 1 0x07 Size of descriptor in bytes
* 1 bDescriptorType 1 0x05 ENDPOINT descriptor type
@@ -1305,17 +1305,17 @@ typedef enum {
* 3 bmAttributes 1 0x02 Endpoint attributes - Bulk
* 4 bNumEndpoints 2 0x0040 maximum packet size
* 5 bInterval 1 0x00 Interval for polling endpoint
- *
+ *
* DATA FORMAT
- *
+ *
* IN Endpoint
- *
+ *
* The device reserves the first two bytes of data on this endpoint to contain the current
* values of the modem and line status registers. In the absence of data, the device
* generates a message consisting of these two status bytes every 40 ms
- *
+ *
* Byte 0: Modem Status
- *
+ *
* Offset Description
* B0 Reserved - must be 1
* B1 Reserved - must be 0
@@ -1325,9 +1325,9 @@ typedef enum {
* B5 Data Set Ready (DSR)
* B6 Ring Indicator (RI)
* B7 Receive Line Signal Detect (RLSD)
- *
+ *
* Byte 1: Line Status
- *
+ *
* Offset Description
* B0 Data Ready (DR)
* B1 Overrun Error (OE)
@@ -1337,7 +1337,7 @@ typedef enum {
* B5 Transmitter Holding Register (THRE)
* B6 Transmitter Empty (TEMT)
* B7 Error in RCVR FIFO
- *
+ *
*/
#define FTDI_RS0_CTS (1 << 4)
#define FTDI_RS0_DSR (1 << 5)
@@ -1355,17 +1355,17 @@ typedef enum {
/*
* OUT Endpoint
- *
+ *
* This device reserves the first bytes of data on this endpoint contain the length
* and port identifier of the message. For the FTDI USB Serial converter the port
* identifier is always 1.
- *
+ *
* Byte 0: Line Status
- *
+ *
* Offset Description
* B0 Reserved - must be 1
* B1 Reserved - must be 0
* B2..7 Length of message - (not including Byte 0)
- *
+ *
*/
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index e8ba2cb5995..d30f736d2cc 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
static int debug;
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 8ce5a56a48e..2e663f1afd5 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -33,7 +33,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -44,7 +44,7 @@
static int initial_mode = 1;
/* debug flag */
-static int debug = 0;
+static int debug;
#define GARMIN_VENDOR_ID 0x091E
@@ -56,7 +56,7 @@ static int debug = 0;
#define VERSION_MINOR 31
#define _STR(s) #s
-#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
+#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
#define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR)
#define DRIVER_AUTHOR "hermann kneissel"
#define DRIVER_DESC "garmin gps driver"
@@ -65,37 +65,37 @@ static int debug = 0;
#define EINVPKT 1000 /* invalid packet structure */
-// size of the header of a packet using the usb protocol
+/* size of the header of a packet using the usb protocol */
#define GARMIN_PKTHDR_LENGTH 12
-// max. possible size of a packet using the serial protocol
-#define MAX_SERIAL_PKT_SIZ (3+255+3)
+/* max. possible size of a packet using the serial protocol */
+#define MAX_SERIAL_PKT_SIZ (3 + 255 + 3)
-// max. possible size of a packet with worst case stuffing
-#define MAX_SERIAL_PKT_SIZ_STUFFED MAX_SERIAL_PKT_SIZ+256
+/* max. possible size of a packet with worst case stuffing */
+#define MAX_SERIAL_PKT_SIZ_STUFFED (MAX_SERIAL_PKT_SIZ + 256)
-// size of a buffer able to hold a complete (no stuffing) packet
-// (the document protocol does not contain packets with a larger
-// size, but in theory a packet may be 64k+12 bytes - if in
-// later protocol versions larger packet sizes occur, this value
-// should be increased accordingly, so the input buffer is always
-// large enough the store a complete packet inclusive header)
-#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
+/* size of a buffer able to hold a complete (no stuffing) packet
+ * (the document protocol does not contain packets with a larger
+ * size, but in theory a packet may be 64k+12 bytes - if in
+ * later protocol versions larger packet sizes occur, this value
+ * should be increased accordingly, so the input buffer is always
+ * large enough the store a complete packet inclusive header) */
+#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
-// size of a buffer able to hold a complete (incl. stuffing) packet
-#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
+/* size of a buffer able to hold a complete (incl. stuffing) packet */
+#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
-// where to place the packet id of a serial packet, so we can
-// prepend the usb-packet header without the need to move the
-// packets data
+/* where to place the packet id of a serial packet, so we can
+ * prepend the usb-packet header without the need to move the
+ * packets data */
#define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2)
-// max. size of incoming private packets (header+1 param)
+/* max. size of incoming private packets (header+1 param) */
#define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4)
#define GARMIN_LAYERID_TRANSPORT 0
#define GARMIN_LAYERID_APPL 20
-// our own layer-id to use for some control mechanisms
+/* our own layer-id to use for some control mechanisms */
#define GARMIN_LAYERID_PRIVATE 0x01106E4B
#define GARMIN_PKTID_PVT_DATA 51
@@ -103,7 +103,7 @@ static int debug = 0;
#define CMND_ABORT_TRANSFER 0
-// packet ids used in private layer
+/* packet ids used in private layer */
#define PRIV_PKTID_SET_DEBUG 1
#define PRIV_PKTID_SET_MODE 2
#define PRIV_PKTID_INFO_REQ 3
@@ -121,7 +121,8 @@ static int debug = 0;
struct garmin_packet {
struct list_head list;
int seq;
- int size; // the real size of the data array, always > 0
+ /* the real size of the data array, always > 0 */
+ int size;
__u8 data[1];
};
@@ -164,7 +165,7 @@ struct garmin_data {
#define MODE_NATIVE 0
#define MODE_GARMIN_SERIAL 1
-// Flags used in garmin_data.flags:
+/* Flags used in garmin_data.flags: */
#define FLAGS_SESSION_REPLY_MASK 0x00C0
#define FLAGS_SESSION_REPLY1_SEEN 0x0080
#define FLAGS_SESSION_REPLY2_SEEN 0x0040
@@ -185,7 +186,7 @@ struct garmin_data {
/* function prototypes */
-static void gsp_next_packet(struct garmin_data * garmin_data_p);
+static void gsp_next_packet(struct garmin_data *garmin_data_p);
static int garmin_write_bulk(struct usb_serial_port *port,
const unsigned char *buf, int count,
int dismiss_ack);
@@ -217,12 +218,13 @@ static unsigned char const PRIVATE_REQ[]
static struct usb_device_id id_table [] = {
- /* the same device id seems to be used by all usb enabled gps devices */
- { USB_DEVICE(GARMIN_VENDOR_ID, 3 ) },
+ /* the same device id seems to be used by all
+ usb enabled GPS devices */
+ { USB_DEVICE(GARMIN_VENDOR_ID, 3) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver garmin_driver = {
.name = "garmin_gps",
@@ -233,9 +235,10 @@ static struct usb_driver garmin_driver = {
};
-static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
+static inline int noResponseFromAppLayer(struct garmin_data *garmin_data_p)
{
- return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
+ return atomic_read(&garmin_data_p->req_count) ==
+ atomic_read(&garmin_data_p->resp_count);
}
@@ -261,10 +264,10 @@ static inline int getDataLength(const __u8 *usbPacket)
*/
static inline int isAbortTrfCmnd(const unsigned char *buf)
{
- if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
- sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
- 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
- sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
+ if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
+ sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
+ 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
+ sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
return 1;
else
return 0;
@@ -275,11 +278,11 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
if (tty && actual_length) {
- usb_serial_debug_data(debug, &port->dev,
+ usb_serial_debug_data(debug, &port->dev,
__func__, actual_length, data);
tty_buffer_request_room(tty, actual_length);
@@ -296,7 +299,7 @@ static void send_to_tty(struct usb_serial_port *port,
/*
* queue a received (usb-)packet for later processing
*/
-static int pkt_add(struct garmin_data * garmin_data_p,
+static int pkt_add(struct garmin_data *garmin_data_p,
unsigned char *data, unsigned int data_length)
{
int state = 0;
@@ -307,7 +310,7 @@ static int pkt_add(struct garmin_data * garmin_data_p,
/* process only packets containg data ... */
if (data_length) {
pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
- GFP_ATOMIC);
+ GFP_ATOMIC);
if (pkt == NULL) {
dev_err(&garmin_data_p->port->dev, "out of memory\n");
return 0;
@@ -325,16 +328,15 @@ static int pkt_add(struct garmin_data * garmin_data_p,
/* in serial mode, if someone is waiting for data from
the device, iconvert and send the next packet to tty. */
- if (result && (state == STATE_GSP_WAIT_DATA)) {
+ if (result && (state == STATE_GSP_WAIT_DATA))
gsp_next_packet(garmin_data_p);
- }
}
return result;
}
/* get the next pending packet */
-static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
+static struct garmin_packet *pkt_pop(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *result = NULL;
@@ -350,7 +352,7 @@ static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
/* free up all queued data */
-static void pkt_clear(struct garmin_data * garmin_data_p)
+static void pkt_clear(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *result = NULL;
@@ -372,7 +374,7 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
******************************************************************************/
/* send an ack packet back to the tty */
-static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
{
__u8 pkt[10];
__u8 cksum = 0;
@@ -391,9 +393,8 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
*ptr++ = pkt_id;
cksum += pkt_id;
- if (pkt_id == DLE) {
+ if (pkt_id == DLE)
*ptr++ = DLE;
- }
*ptr++ = 0;
*ptr++ = 0xFF & (-cksum);
@@ -415,12 +416,12 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
* at GSP_INITIAL_OFFSET.
*
* count - number of bytes in the input buffer including space reserved for
- * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
+ * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
* (including pkt-id, data-length a. cksum)
*/
-static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
{
- const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+ const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
int cksum = 0;
@@ -440,8 +441,8 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
cksum += *recpkt++;
cksum += *recpkt++;
- // sanity check, remove after test ...
- if ((__u8*)&(usbdata[3]) != recpkt) {
+ /* sanity check, remove after test ... */
+ if ((__u8 *)&(usbdata[3]) != recpkt) {
dbg("%s - ptr mismatch %p - %p",
__func__, &(usbdata[4]), recpkt);
return -EINVPKT;
@@ -462,7 +463,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
usbdata[1] = __cpu_to_le32(pktid);
usbdata[2] = __cpu_to_le32(size);
- garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer,
+ garmin_write_bulk(garmin_data_p->port, garmin_data_p->inbuffer,
GARMIN_PKTHDR_LENGTH+size, 0);
/* if this was an abort-transfer command, flush all
@@ -495,7 +496,7 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
* if the input is an abort command, drop all queued data.
*/
-static int gsp_receive(struct garmin_data * garmin_data_p,
+static int gsp_receive(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
unsigned long flags;
@@ -504,10 +505,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
int i = 0;
__u8 *dest;
int size;
- // dleSeen: set if last byte read was a DLE
+ /* dleSeen: set if last byte read was a DLE */
int dleSeen;
- // skip: if set, skip incoming data until possible start of
- // new packet
+ /* skip: if set, skip incoming data until possible start of
+ * new packet
+ */
int skip;
__u8 data;
@@ -521,14 +523,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
dbg("%s - dle=%d skip=%d size=%d count=%d",
__func__, dleSeen, skip, size, count);
- if (size == 0) {
+ if (size == 0)
size = GSP_INITIAL_OFFSET;
- }
while (offs < count) {
data = *(buf+offs);
- offs ++;
+ offs++;
if (data == DLE) {
if (skip) { /* start of a new pkt */
@@ -554,9 +555,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
ack_or_nak_seen = NAK;
dbg("NAK packet complete.");
} else {
- dbg("packet complete "
- "- id=0x%X.",
- 0xFF & data);
+ dbg("packet complete - id=0x%X.",
+ 0xFF & data);
gsp_rec_packet(garmin_data_p, size);
}
@@ -589,7 +589,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
garmin_data_p->insize = size;
- // copy flags back to structure
+ /* copy flags back to structure */
if (skip)
garmin_data_p->flags |= FLAGS_GSP_SKIP;
else
@@ -600,16 +600,13 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
else
garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN;
- if (ack_or_nak_seen) {
+ if (ack_or_nak_seen)
garmin_data_p->state = STATE_GSP_WAIT_DATA;
- }
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- if (ack_or_nak_seen) {
+ if (ack_or_nak_seen)
gsp_next_packet(garmin_data_p);
- }
-
return count;
}
@@ -623,7 +620,7 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
*
* return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
*/
-static int gsp_send(struct garmin_data * garmin_data_p,
+static int gsp_send(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
const unsigned char *src;
@@ -631,11 +628,11 @@ static int gsp_send(struct garmin_data * garmin_data_p,
int pktid = 0;
int datalen = 0;
int cksum = 0;
- int i=0;
+ int i = 0;
int k;
dbg("%s - state %d - %d bytes.", __func__,
- garmin_data_p->state, count);
+ garmin_data_p->state, count);
k = garmin_data_p->outsize;
if ((k+count) > GPS_OUT_BUFSIZ) {
@@ -650,7 +647,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
if (k >= GARMIN_PKTHDR_LENGTH) {
pktid = getPacketId(garmin_data_p->outbuffer);
- datalen= getDataLength(garmin_data_p->outbuffer);
+ datalen = getDataLength(garmin_data_p->outbuffer);
i = GARMIN_PKTHDR_LENGTH + datalen;
if (k < i)
return 0;
@@ -658,19 +655,18 @@ static int gsp_send(struct garmin_data * garmin_data_p,
return 0;
}
- dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
- k, i);
+ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i);
/* garmin_data_p->outbuffer now contains a complete packet */
usb_serial_debug_data(debug, &garmin_data_p->port->dev,
- __func__, k, garmin_data_p->outbuffer);
+ __func__, k, garmin_data_p->outbuffer);
garmin_data_p->outsize = 0;
if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) {
- dbg("not an application packet (%d)",
- getLayerId(garmin_data_p->outbuffer));
+ dbg("not an application packet (%d)",
+ getLayerId(garmin_data_p->outbuffer));
return -1;
}
@@ -688,14 +684,14 @@ static int gsp_send(struct garmin_data * garmin_data_p,
k = 0;
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
- for (i=0; i<datalen; i++) {
+ for (i = 0; i < datalen; i++) {
if (*src++ == DLE)
k++;
}
src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
if (k > (GARMIN_PKTHDR_LENGTH-2)) {
- /* can't add stuffing DLEs in place, move data to end
+ /* can't add stuffing DLEs in place, move data to end
of buffer ... */
dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
memcpy(dst, src, datalen);
@@ -712,14 +708,14 @@ static int gsp_send(struct garmin_data * garmin_data_p,
if (datalen == DLE)
*dst++ = DLE;
- for (i=0; i<datalen; i++) {
+ for (i = 0; i < datalen; i++) {
__u8 c = *src++;
*dst++ = c;
cksum += c;
if (c == DLE)
*dst++ = DLE;
}
-
+
cksum = 0xFF & -cksum;
*dst++ = cksum;
if (cksum == DLE)
@@ -744,7 +740,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
/*
* Process the next pending data packet - if there is one
*/
-static void gsp_next_packet(struct garmin_data * garmin_data_p)
+static void gsp_next_packet(struct garmin_data *garmin_data_p)
{
struct garmin_packet *pkt = NULL;
@@ -774,17 +770,17 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
* buf contains the data read, it may span more than one packet
* or even incomplete packets
*/
-static int nat_receive(struct garmin_data * garmin_data_p,
+static int nat_receive(struct garmin_data *garmin_data_p,
const unsigned char *buf, int count)
{
unsigned long flags;
- __u8 * dest;
+ __u8 *dest;
int offs = 0;
int result = count;
int len;
while (offs < count) {
- // if buffer contains header, copy rest of data
+ /* if buffer contains header, copy rest of data */
if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH)
len = GARMIN_PKTHDR_LENGTH
+getDataLength(garmin_data_p->inbuffer);
@@ -792,9 +788,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = GARMIN_PKTHDR_LENGTH;
if (len >= GPS_IN_BUFSIZ) {
- /* seem to be an invalid packet, ignore rest of input */
- dbg("%s - packet size too large: %d",
- __func__, len);
+ /* seems to be an invalid packet, ignore rest
+ of input */
+ dbg("%s - packet size too large: %d", __func__, len);
garmin_data_p->insize = 0;
count = 0;
result = -EINVPKT;
@@ -804,7 +800,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = (count-offs);
if (len > 0) {
dest = garmin_data_p->inbuffer
- +garmin_data_p->insize;
+ + garmin_data_p->insize;
memcpy(dest, buf+offs, len);
garmin_data_p->insize += len;
offs += len;
@@ -816,17 +812,19 @@ static int nat_receive(struct garmin_data * garmin_data_p,
len = GARMIN_PKTHDR_LENGTH+
getDataLength(garmin_data_p->inbuffer);
if (garmin_data_p->insize >= len) {
- garmin_write_bulk (garmin_data_p->port,
- garmin_data_p->inbuffer,
- len, 0);
+ garmin_write_bulk(garmin_data_p->port,
+ garmin_data_p->inbuffer,
+ len, 0);
garmin_data_p->insize = 0;
/* if this was an abort-transfer command,
flush all queued data. */
if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
- spin_lock_irqsave(&garmin_data_p->lock, flags);
+ spin_lock_irqsave(&garmin_data_p->lock,
+ flags);
garmin_data_p->flags |= FLAGS_DROP_DATA;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(
+ &garmin_data_p->lock, flags);
pkt_clear(garmin_data_p);
}
}
@@ -842,7 +840,7 @@ static int nat_receive(struct garmin_data * garmin_data_p,
static void priv_status_resp(struct usb_serial_port *port)
{
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
__le32 *pkt = (__le32 *)garmin_data_p->privpkt;
pkt[0] = __cpu_to_le32(GARMIN_LAYERID_PRIVATE);
@@ -852,7 +850,7 @@ static void priv_status_resp(struct usb_serial_port *port)
pkt[4] = __cpu_to_le32(garmin_data_p->mode);
pkt[5] = __cpu_to_le32(garmin_data_p->serial_num);
- send_to_tty(port, (__u8*)pkt, 6*4);
+ send_to_tty(port, (__u8 *)pkt, 6 * 4);
}
@@ -864,7 +862,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
{
unsigned long flags;
int status;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
@@ -872,8 +870,8 @@ static int process_resetdev_request(struct usb_serial_port *port)
garmin_data_p->serial_num = 0;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- usb_kill_urb (port->interrupt_in_urb);
- dbg("%s - usb_reset_device", __func__ );
+ usb_kill_urb(port->interrupt_in_urb);
+ dbg("%s - usb_reset_device", __func__);
status = usb_reset_device(port->serial->dev);
if (status)
dbg("%s - usb_reset_device failed: %d",
@@ -886,7 +884,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
/*
* clear all cached data
*/
-static int garmin_clear(struct garmin_data * garmin_data_p)
+static int garmin_clear(struct garmin_data *garmin_data_p)
{
unsigned long flags;
int status = 0;
@@ -896,8 +894,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
if (port != NULL && atomic_read(&garmin_data_p->resp_count)) {
/* send a terminate command */
status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
- sizeof(GARMIN_STOP_TRANSFER_REQ),
- 1);
+ sizeof(GARMIN_STOP_TRANSFER_REQ), 1);
}
/* flush all queued data */
@@ -920,28 +917,26 @@ static int garmin_init_session(struct usb_serial_port *port)
{
unsigned long flags;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
int status = 0;
if (status == 0) {
- usb_kill_urb (port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
dbg("%s - adding interrupt input", __func__);
port->interrupt_in_urb->dev = serial->dev;
status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (status)
dev_err(&serial->dev->dev,
- "%s - failed submitting interrupt urb,"
- " error %d\n",
- __func__, status);
+ "%s - failed submitting interrupt urb, error %d\n",
+ __func__, status);
}
if (status == 0) {
dbg("%s - starting session ...", __func__);
garmin_data_p->state = STATE_ACTIVE;
status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
- sizeof(GARMIN_START_SESSION_REQ),
- 0);
+ sizeof(GARMIN_START_SESSION_REQ), 0);
if (status >= 0) {
@@ -951,14 +946,14 @@ static int garmin_init_session(struct usb_serial_port *port)
/* not needed, but the win32 driver does it too ... */
status = garmin_write_bulk(port,
- GARMIN_START_SESSION_REQ2,
- sizeof(GARMIN_START_SESSION_REQ2),
- 0);
+ GARMIN_START_SESSION_REQ2,
+ sizeof(GARMIN_START_SESSION_REQ2), 0);
if (status >= 0) {
status = 0;
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->ignorePkts++;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(&garmin_data_p->lock,
+ flags);
}
}
}
@@ -970,11 +965,12 @@ static int garmin_init_session(struct usb_serial_port *port)
-static int garmin_open (struct usb_serial_port *port, struct file *filp)
+static int garmin_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
unsigned long flags;
int status = 0;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -983,8 +979,8 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->mode = initial_mode;
@@ -995,23 +991,22 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* shutdown any bulk reads that might be going on */
- usb_kill_urb (port->write_urb);
- usb_kill_urb (port->read_urb);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
- if (garmin_data_p->state == STATE_RESET) {
+ if (garmin_data_p->state == STATE_RESET)
status = garmin_init_session(port);
- }
garmin_data_p->state = STATE_ACTIVE;
-
return status;
}
-static void garmin_close (struct usb_serial_port *port, struct file * filp)
+static void garmin_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
port->number, garmin_data_p->mode,
@@ -1025,8 +1020,8 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
garmin_clear(garmin_data_p);
/* shutdown our urbs */
- usb_kill_urb (port->read_urb);
- usb_kill_urb (port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->write_urb);
if (!port->serial->disconnected) {
if (noResponseFromAppLayer(garmin_data_p) ||
@@ -1042,21 +1037,22 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
mutex_unlock(&port->serial->disc_mutex);
}
-
-static void garmin_write_bulk_callback (struct urb *urb)
+static void garmin_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
int status = urb->status;
if (port) {
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p =
+ usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
&& (garmin_data_p->mode == MODE_GARMIN_SERIAL)) {
- gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]);
+ gsp_send_ack(garmin_data_p,
+ ((__u8 *)urb->transfer_buffer)[4]);
}
if (status) {
@@ -1070,20 +1066,21 @@ static void garmin_write_bulk_callback (struct urb *urb)
usb_serial_port_softint(port);
}
- /* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */
+ /* Ignore errors that resulted from garmin_write_bulk with
+ dismiss_ack = 1 */
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
}
-static int garmin_write_bulk (struct usb_serial_port *port,
+static int garmin_write_bulk(struct usb_serial_port *port,
const unsigned char *buf, int count,
int dismiss_ack)
{
unsigned long flags;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
struct urb *urb;
unsigned char *buffer;
int status;
@@ -1095,7 +1092,7 @@ static int garmin_write_bulk (struct usb_serial_port *port,
garmin_data_p->flags &= ~FLAGS_DROP_DATA;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- buffer = kmalloc (count, GFP_ATOMIC);
+ buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
dev_err(&port->dev, "out of memory\n");
return -ENOMEM;
@@ -1104,17 +1101,17 @@ static int garmin_write_bulk (struct usb_serial_port *port,
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
dev_err(&port->dev, "no more free urbs\n");
- kfree (buffer);
+ kfree(buffer);
return -ENOMEM;
}
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- usb_fill_bulk_urb (urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
- port->bulk_out_endpointAddress),
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
buffer, count,
garmin_write_bulk_callback,
dismiss_ack ? NULL : port);
@@ -1132,33 +1129,29 @@ static int garmin_write_bulk (struct usb_serial_port *port,
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
dev_err(&port->dev,
- "%s - usb_submit_urb(write bulk) "
- "failed with status = %d\n",
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
__func__, status);
count = status;
}
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
- usb_free_urb (urb);
+ usb_free_urb(urb);
return count;
}
-
-
-static int garmin_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
int pktid, pktsiz, len;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
/* check for our private packets */
if (count >= GARMIN_PKTHDR_LENGTH) {
-
len = PRIVPKTSIZ;
if (count < len)
len = count;
@@ -1169,15 +1162,16 @@ static int garmin_write (struct usb_serial_port *port,
pktid = getPacketId(garmin_data_p->privpkt);
if (count == (GARMIN_PKTHDR_LENGTH+pktsiz)
- && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+ && GARMIN_LAYERID_PRIVATE ==
+ getLayerId(garmin_data_p->privpkt)) {
dbg("%s - processing private request %d",
__func__, pktid);
- // drop all unfinished transfers
+ /* drop all unfinished transfers */
garmin_clear(garmin_data_p);
- switch(pktid) {
+ switch (pktid) {
case PRIV_PKTID_SET_DEBUG:
if (pktsiz != 4)
@@ -1226,44 +1220,31 @@ static int garmin_write (struct usb_serial_port *port,
}
-static int garmin_write_room (struct usb_serial_port *port)
+static int garmin_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
/*
* Report back the bytes currently available in the output buffer.
*/
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
return GPS_OUT_BUFSIZ-garmin_data_p->outsize;
}
-static int garmin_chars_in_buffer (struct usb_serial_port *port)
-{
- /*
- * Report back the number of bytes currently in our input buffer.
- * Will this lock up the driver - the buffer contains an incomplete
- * package which will not be written to the device until it
- * has been completed ?
- */
- //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
- //return garmin_data_p->insize;
- return 0;
-}
-
-
-static void garmin_read_process(struct garmin_data * garmin_data_p,
+static void garmin_read_process(struct garmin_data *garmin_data_p,
unsigned char *data, unsigned data_length)
{
if (garmin_data_p->flags & FLAGS_DROP_DATA) {
/* abort-transfer cmd is actice */
dbg("%s - pkt dropped", __func__);
} else if (garmin_data_p->state != STATE_DISCONNECTED &&
- garmin_data_p->state != STATE_RESET ) {
+ garmin_data_p->state != STATE_RESET) {
/* remember any appl.layer packets, so we know
if a reset is required or not when closing
the device */
if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
- sizeof(GARMIN_APP_LAYER_REPLY))) {
+ sizeof(GARMIN_APP_LAYER_REPLY))) {
atomic_inc(&garmin_data_p->resp_count);
}
@@ -1273,9 +1254,8 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
if (garmin_data_p->flags & FLAGS_QUEUING) {
pkt_add(garmin_data_p, data, data_length);
} else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
- if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+ if (getLayerId(data) == GARMIN_LAYERID_APPL)
pkt_add(garmin_data_p, data, data_length);
- }
} else {
send_to_tty(garmin_data_p->port, data, data_length);
}
@@ -1283,12 +1263,12 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
}
-static void garmin_read_bulk_callback (struct urb *urb)
+static void garmin_read_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
int retval;
@@ -1306,7 +1286,7 @@ static void garmin_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev,
+ usb_serial_debug_data(debug, &port->dev,
__func__, urb->actual_length, data);
garmin_read_process(garmin_data_p, data, urb->actual_length);
@@ -1340,13 +1320,13 @@ static void garmin_read_bulk_callback (struct urb *urb)
}
-static void garmin_read_int_callback (struct urb *urb)
+static void garmin_read_int_callback(struct urb *urb)
{
unsigned long flags;
int retval;
struct usb_serial_port *port = urb->context;
struct usb_serial *serial = port->serial;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
@@ -1372,30 +1352,31 @@ static void garmin_read_int_callback (struct urb *urb)
if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
- sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+ sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
dbg("%s - bulk data available.", __func__);
if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
/* bulk data available */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
- port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
garmin_read_bulk_callback, port);
retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (retval) {
dev_err(&port->dev,
- "%s - failed submitting read urb, error %d\n",
- __func__, retval);
+ "%s - failed submitting read urb, error %d\n",
+ __func__, retval);
} else {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
/* do not send this packet to the user */
garmin_data_p->ignorePkts = 1;
- spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ spin_unlock_irqrestore(&garmin_data_p->lock,
+ flags);
}
} else {
/* bulk-in transfer still active */
@@ -1406,15 +1387,15 @@ static void garmin_read_int_callback (struct urb *urb)
} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
&& 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
- sizeof(GARMIN_START_SESSION_REPLY))) {
+ sizeof(GARMIN_START_SESSION_REPLY))) {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
/* save the serial number */
- garmin_data_p->serial_num
- = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+ garmin_data_p->serial_num = __le32_to_cpup(
+ (__le32 *)(data+GARMIN_PKTHDR_LENGTH));
dbg("%s - start-of-session reply seen - serial %u.",
__func__, garmin_data_p->serial_num);
@@ -1433,7 +1414,7 @@ static void garmin_read_int_callback (struct urb *urb)
}
port->interrupt_in_urb->dev = port->serial->dev;
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&urb->dev->dev,
"%s - Error %d submitting interrupt urb\n",
@@ -1446,7 +1427,7 @@ static void garmin_read_int_callback (struct urb *urb)
* and then sets a timer to call itself again until all queued data
* is sent.
*/
-static int garmin_flush_queue(struct garmin_data * garmin_data_p)
+static int garmin_flush_queue(struct garmin_data *garmin_data_p)
{
unsigned long flags;
struct garmin_packet *pkt;
@@ -1468,10 +1449,11 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p)
}
-static void garmin_throttle (struct usb_serial_port *port)
+static void garmin_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
/* set flag, data received will be put into a queue
@@ -1482,10 +1464,11 @@ static void garmin_throttle (struct usb_serial_port *port)
}
-static void garmin_unthrottle (struct usb_serial_port *port)
+static void garmin_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1507,8 +1490,6 @@ static void garmin_unthrottle (struct usb_serial_port *port)
}
}
-
-
/*
* The timer is currently only used to send queued packets to
* the tty in cases where the protocol provides no own handshaking
@@ -1526,11 +1507,11 @@ static void timeout_handler(unsigned long data)
-static int garmin_attach (struct usb_serial *serial)
+static int garmin_attach(struct usb_serial *serial)
{
int status = 0;
struct usb_serial_port *port = serial->port[0];
- struct garmin_data * garmin_data_p = NULL;
+ struct garmin_data *garmin_data_p = NULL;
dbg("%s", __func__);
@@ -1542,7 +1523,7 @@ static int garmin_attach (struct usb_serial *serial)
init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist);
- //garmin_data_p->timer.expires = jiffies + session_timeout;
+ /* garmin_data_p->timer.expires = jiffies + session_timeout; */
garmin_data_p->timer.data = (unsigned long)garmin_data_p;
garmin_data_p->timer.function = timeout_handler;
garmin_data_p->port = port;
@@ -1556,16 +1537,16 @@ static int garmin_attach (struct usb_serial *serial)
}
-static void garmin_shutdown (struct usb_serial *serial)
+static void garmin_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
- struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
dbg("%s", __func__);
- usb_kill_urb (port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
- kfree (garmin_data_p);
+ kfree(garmin_data_p);
usb_set_serial_port_data(port, NULL);
}
@@ -1588,7 +1569,6 @@ static struct usb_serial_driver garmin_device = {
.shutdown = garmin_shutdown,
.write = garmin_write,
.write_room = garmin_write_room,
- .chars_in_buffer = garmin_chars_in_buffer,
.write_bulk_callback = garmin_write_bulk_callback,
.read_bulk_callback = garmin_read_bulk_callback,
.read_int_callback = garmin_read_int_callback,
@@ -1596,7 +1576,7 @@ static struct usb_serial_driver garmin_device = {
-static int __init garmin_init (void)
+static int __init garmin_init(void)
{
int retval;
@@ -1616,10 +1596,10 @@ failed_garmin_register:
}
-static void __exit garmin_exit (void)
+static void __exit garmin_exit(void)
{
- usb_deregister (&garmin_driver);
- usb_serial_deregister (&garmin_device);
+ usb_deregister(&garmin_driver);
+ usb_serial_deregister(&garmin_device);
}
@@ -1628,8 +1608,8 @@ static void __exit garmin_exit (void)
module_init(garmin_init);
module_exit(garmin_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IWUSR | S_IRUGO);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 537f12a027c..fe84c88ec20 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -18,7 +18,7 @@
#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
static int debug;
@@ -81,7 +81,7 @@ static int generic_probe(struct usb_interface *interface,
}
#endif
-int usb_serial_generic_register (int _debug)
+int usb_serial_generic_register(int _debug)
{
int retval = 0;
@@ -89,10 +89,11 @@ int usb_serial_generic_register (int _debug)
#ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
- generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+ generic_device_ids[0].match_flags =
+ USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
- retval = usb_serial_register (&usb_serial_generic_device);
+ retval = usb_serial_register(&usb_serial_generic_device);
if (retval)
goto exit;
retval = usb_register(&generic_driver);
@@ -103,16 +104,17 @@ exit:
return retval;
}
-void usb_serial_generic_deregister (void)
+void usb_serial_generic_deregister(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_deregister(&generic_driver);
- usb_serial_deregister (&usb_serial_generic_device);
+ usb_serial_deregister(&usb_serial_generic_device);
#endif
}
-int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+int usb_serial_generic_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
@@ -120,11 +122,11 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
- /* force low_latency on so that our tty_push actually forces the data through,
- otherwise it is scheduled, and with high data rates (like with OHCI) data
- can get lost. */
- if (port->tty)
- port->tty->low_latency = 1;
+ /* force low_latency on so that our tty_push actually forces the data
+ through, otherwise it is scheduled, and with high data rates (like
+ with OHCI) data can get lost. */
+ if (tty)
+ tty->low_latency = 1;
/* clear the throttle flags */
spin_lock_irqsave(&port->lock, flags);
@@ -135,8 +137,9 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
/* if we have a bulk endpoint, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
@@ -145,14 +148,16 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
}
return result;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_open);
-static void generic_cleanup (struct usb_serial_port *port)
+static void generic_cleanup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -182,7 +187,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
#endif
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- if (port->open_count && port->read_urb) {
+ if (port->port.count && port->read_urb) {
r = usb_submit_urb(port->read_urb, GFP_NOIO);
if (r < 0)
c++;
@@ -192,13 +197,15 @@ int usb_serial_generic_resume(struct usb_serial *serial)
return c ? -EIO : 0;
}
-void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+void usb_serial_generic_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
- generic_cleanup (port);
+ generic_cleanup(port);
}
-int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+int usb_serial_generic_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int result;
@@ -208,7 +215,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
- return (0);
+ return 0;
}
/* only do something if we have a bulk out endpoint */
@@ -223,27 +230,32 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
port->write_urb_busy = 1;
spin_unlock_irqrestore(&port->lock, flags);
- count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+ count = (count > port->bulk_out_size) ?
+ port->bulk_out_size : count;
- memcpy (port->write_urb->transfer_buffer, buf, count);
+ memcpy(port->write_urb->transfer_buffer, buf, count);
data = port->write_urb->transfer_buffer;
usb_serial_debug_data(debug, &port->dev, __func__, count, data);
/* set up our urb */
- usb_fill_bulk_urb (port->write_urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
- port->bulk_out_endpointAddress),
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
- ((serial->type->write_bulk_callback) ?
+ ((serial->type->write_bulk_callback) ?
serial->type->write_bulk_callback :
- usb_serial_generic_write_bulk_callback), port);
+ usb_serial_generic_write_bulk_callback),
+ port);
/* send the data out the bulk port */
port->write_urb_busy = 1;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
- /* don't have to grab the lock here, as we will retry if != 0 */
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
+ /* don't have to grab the lock here, as we will
+ retry if != 0 */
port->write_urb_busy = 0;
} else
result = count;
@@ -255,8 +267,9 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
return 0;
}
-int usb_serial_generic_write_room (struct usb_serial_port *port)
+int usb_serial_generic_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int room = 0;
@@ -272,8 +285,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
return room;
}
-int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int chars = 0;
@@ -286,7 +300,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
}
dbg("%s - returns %d", __func__, chars);
- return (chars);
+ return chars;
}
@@ -297,24 +311,26 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
int result;
/* Continue reading from device */
- usb_fill_bulk_urb (urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
- port->bulk_in_endpointAddress),
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
urb->transfer_buffer,
urb->transfer_buffer_length,
- ((serial->type->read_bulk_callback) ?
- serial->type->read_bulk_callback :
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(urb, mem_flags);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
}
/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
{
struct urb *urb = port->read_urb;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
int room;
/* Push data to tty */
@@ -329,7 +345,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
resubmit_read_urb(port, GFP_ATOMIC);
}
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+void usb_serial_generic_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -344,20 +360,21 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
- if (!(port->throttled = port->throttle_req)) {
+ port->throttled = port->throttle_req;
+ if (!port->throttled) {
spin_unlock_irqrestore(&port->lock, flags);
flush_and_resubmit_read_urb(port);
- } else {
+ } else
spin_unlock_irqrestore(&port->lock, flags);
- }
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
-void usb_serial_generic_write_bulk_callback (struct urb *urb)
+void usb_serial_generic_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -374,8 +391,9 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb)
}
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
-void usb_serial_generic_throttle (struct usb_serial_port *port)
+void usb_serial_generic_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
@@ -387,8 +405,9 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
spin_unlock_irqrestore(&port->lock, flags);
}
-void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+void usb_serial_generic_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int was_throttled;
unsigned long flags;
@@ -406,15 +425,14 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
}
}
-void usb_serial_generic_shutdown (struct usb_serial *serial)
+void usb_serial_generic_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
generic_cleanup(serial->port[i]);
- }
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 75b88b356eb..ab905869e95 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -9,7 +9,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*/
#include <linux/kernel.h>
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 2fd449bcfa3..bfa508ddb0f 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -44,7 +44,7 @@
#include <linux/wait.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "io_edgeport.h"
@@ -66,16 +66,16 @@
/* receive port state */
enum RXSTATE {
- EXPECT_HDR1 = 0, /* Expect header byte 1 */
- EXPECT_HDR2 = 1, /* Expect header byte 2 */
- EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */
- EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */
+ EXPECT_HDR1 = 0, /* Expect header byte 1 */
+ EXPECT_HDR2 = 1, /* Expect header byte 2 */
+ EXPECT_DATA = 2, /* Expect 'RxBytesRemaining' data */
+ EXPECT_HDR3 = 3, /* Expect header byte 3 (for status hdrs only) */
};
-/* Transmit Fifo
- * This Transmit queue is an extension of the edgeport Rx buffer.
- * The maximum amount of data buffered in both the edgeport
+/* Transmit Fifo
+ * This Transmit queue is an extension of the edgeport Rx buffer.
+ * The maximum amount of data buffered in both the edgeport
* Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits.
*/
struct TxFifo {
@@ -132,12 +132,12 @@ struct edgeport_serial {
int is_epic; /* flag if EPiC device or not */
__u8 interrupt_in_endpoint; /* the interrupt endpoint handle */
- unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */
- struct urb * interrupt_read_urb; /* our interrupt urb */
+ unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */
+ struct urb *interrupt_read_urb; /* our interrupt urb */
__u8 bulk_in_endpoint; /* the bulk in endpoint handle */
- unsigned char * bulk_in_buffer; /* the buffer we use for the bulk in endpoint */
- struct urb * read_urb; /* our bulk read urb */
+ unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */
+ struct urb *read_urb; /* our bulk read urb */
bool read_in_progress;
spinlock_t es_lock;
@@ -162,16 +162,17 @@ struct divisor_table_entry {
__u16 Divisor;
};
-//
-// Define table of divisors for Rev A EdgePort/4 hardware
-// These assume a 3.6864MHz crystal, the standard /16, and
-// MCR.7 = 0.
-//
+/*
+ * Define table of divisors for Rev A EdgePort/4 hardware
+ * These assume a 3.6864MHz crystal, the standard /16, and
+ * MCR.7 = 0.
+ */
+
static const struct divisor_table_entry divisor_table[] = {
- { 50, 4608},
- { 75, 3072},
- { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */
- { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */
+ { 50, 4608},
+ { 75, 3072},
+ { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */
+ { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */
{ 150, 1536},
{ 300, 768},
{ 600, 384},
@@ -194,64 +195,86 @@ static int debug;
static int low_latency = 1; /* tty low latency flag, on by default */
-static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
/* local function prototypes */
/* function prototypes for all URB callbacks */
-static void edge_interrupt_callback (struct urb *urb);
-static void edge_bulk_in_callback (struct urb *urb);
-static void edge_bulk_out_data_callback (struct urb *urb);
-static void edge_bulk_out_cmd_callback (struct urb *urb);
+static void edge_interrupt_callback(struct urb *urb);
+static void edge_bulk_in_callback(struct urb *urb);
+static void edge_bulk_out_data_callback(struct urb *urb);
+static void edge_bulk_out_cmd_callback(struct urb *urb);
/* function prototypes for the usbserial callbacks */
-static int edge_open (struct usb_serial_port *port, struct file *filp);
-static void edge_close (struct usb_serial_port *port, struct file *filp);
-static int edge_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int edge_write_room (struct usb_serial_port *port);
-static int edge_chars_in_buffer (struct usb_serial_port *port);
-static void edge_throttle (struct usb_serial_port *port);
-static void edge_unthrottle (struct usb_serial_port *port);
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void edge_break (struct usb_serial_port *port, int break_state);
-static int edge_tiocmget (struct usb_serial_port *port, struct file *file);
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int edge_startup (struct usb_serial *serial);
-static void edge_shutdown (struct usb_serial *serial);
-
+static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int edge_write_room(struct tty_struct *tty);
+static int edge_chars_in_buffer(struct tty_struct *tty);
+static void edge_throttle(struct tty_struct *tty);
+static void edge_unthrottle(struct tty_struct *tty);
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios);
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void edge_break(struct tty_struct *tty, int break_state);
+static int edge_tiocmget(struct tty_struct *tty, struct file *file);
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static int edge_startup(struct usb_serial *serial);
+static void edge_shutdown(struct usb_serial *serial);
#include "io_tables.h" /* all of the devices that this driver supports */
/* function prototypes for all of our local functions */
-static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
-static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);
-static void edge_tty_recv (struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
-static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr);
-static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data);
-static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param);
-static int calc_baud_rate_divisor (int baud_rate, int *divisor);
-static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios);
-static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
-static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
-static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
-
-static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
-static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static void get_manufacturing_desc (struct edgeport_serial *edge_serial);
-static void get_boot_desc (struct edgeport_serial *edge_serial);
-static void load_application_firmware (struct edgeport_serial *edge_serial);
-
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size);
-
-
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
+
+static void process_rcvd_data(struct edgeport_serial *edge_serial,
+ unsigned char *buffer, __u16 bufferLength);
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+ __u8 byte2, __u8 byte3);
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length);
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr);
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+ __u8 lsr, __u8 data);
+static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
+ __u8 param);
+static int calc_baud_rate_divisor(int baud_rate, int *divisor);
+static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+ int baudRate);
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port,
+ struct ktermios *old_termios);
+static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
+ __u8 regNum, __u8 regValue);
+static int write_cmd_usb(struct edgeport_port *edge_port,
+ unsigned char *buffer, int writeLength);
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+ struct edgeport_port *edge_port);
+
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data);
+static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, __u8 *data);
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data);
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial);
+static void get_boot_desc(struct edgeport_serial *edge_serial);
+static void load_application_firmware(struct edgeport_serial *edge_serial);
+
+static void unicode_to_ascii(char *string, int buflen,
+ __le16 *unicode, int unicode_size);
+
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
/************************************************************************
* *
@@ -261,7 +284,7 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic
* embedded in this driver *
* *
************************************************************************/
-static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
{
__u32 BootCurVer;
__u32 BootNewVer;
@@ -275,16 +298,14 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
int response;
switch (edge_serial->product_info.iDownloadFile) {
- case EDGE_DOWNLOAD_FILE_I930:
- fw_name = "edgeport/boot.fw";
- break;
-
- case EDGE_DOWNLOAD_FILE_80251:
- fw_name = "edgeport/boot2.fw";
- break;
-
- default:
- return;
+ case EDGE_DOWNLOAD_FILE_I930:
+ fw_name = "edgeport/boot.fw";
+ break;
+ case EDGE_DOWNLOAD_FILE_80251:
+ fw_name = "edgeport/boot2.fw";
+ break;
+ default:
+ return;
}
response = request_ihex_firmware(&fw, fw_name,
@@ -300,7 +321,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
BootMinorVersion = rec->data[1];
BootBuildNumber = (rec->data[2] << 8) | rec->data[3];
- // Check Boot Image Version
+ /* Check Boot Image Version */
BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
(edge_serial->boot_descriptor.MinorVersion << 16) +
le16_to_cpu(edge_serial->boot_descriptor.BuildNumber);
@@ -352,29 +373,29 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
* Get string descriptor from device *
* *
************************************************************************/
-static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+static int get_string(struct usb_device *dev, int Id, char *string, int buflen)
{
struct usb_string_descriptor StringDesc;
struct usb_string_descriptor *pStringDesc;
- dbg("%s - USB String ID = %d", __func__, Id );
+ dbg("%s - USB String ID = %d", __func__, Id);
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+ &StringDesc, sizeof(StringDesc)))
return 0;
- }
- pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
- if (!pStringDesc) {
+ pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+ if (!pStringDesc)
return 0;
- }
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+ pStringDesc, StringDesc.bLength)) {
kfree(pStringDesc);
return 0;
}
- unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
+ unicode_to_ascii(string, buflen,
+ pStringDesc->wData, pStringDesc->bLength/2);
kfree(pStringDesc);
dbg("%s - USB String %s", __func__, string);
@@ -388,24 +409,24 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
* Get string descriptor from device
*
************************************************************************/
-static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc)
+static int get_string_desc(struct usb_device *dev, int Id,
+ struct usb_string_descriptor **pRetDesc)
{
struct usb_string_descriptor StringDesc;
struct usb_string_descriptor *pStringDesc;
- dbg("%s - USB String ID = %d", __func__, Id );
+ dbg("%s - USB String ID = %d", __func__, Id);
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc,
+ sizeof(StringDesc)))
return 0;
- }
- pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
- if (!pStringDesc) {
+ pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+ if (!pStringDesc)
return -1;
- }
- if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+ if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc,
+ StringDesc.bLength)) {
kfree(pStringDesc);
return -1;
}
@@ -417,25 +438,30 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
static void dump_product_info(struct edgeport_product_info *product_info)
{
- // Dump Product Info structure
+ /* Dump Product Info structure */
dbg("**Product Information:");
- dbg(" ProductId %x", product_info->ProductId );
- dbg(" NumPorts %d", product_info->NumPorts );
- dbg(" ProdInfoVer %d", product_info->ProdInfoVer );
+ dbg(" ProductId %x", product_info->ProductId);
+ dbg(" NumPorts %d", product_info->NumPorts);
+ dbg(" ProdInfoVer %d", product_info->ProdInfoVer);
dbg(" IsServer %d", product_info->IsServer);
- dbg(" IsRS232 %d", product_info->IsRS232 );
- dbg(" IsRS422 %d", product_info->IsRS422 );
- dbg(" IsRS485 %d", product_info->IsRS485 );
- dbg(" RomSize %d", product_info->RomSize );
- dbg(" RamSize %d", product_info->RamSize );
- dbg(" CpuRev %x", product_info->CpuRev );
+ dbg(" IsRS232 %d", product_info->IsRS232);
+ dbg(" IsRS422 %d", product_info->IsRS422);
+ dbg(" IsRS485 %d", product_info->IsRS485);
+ dbg(" RomSize %d", product_info->RomSize);
+ dbg(" RamSize %d", product_info->RamSize);
+ dbg(" CpuRev %x", product_info->CpuRev);
dbg(" BoardRev %x", product_info->BoardRev);
dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion,
product_info->BootMinorVersion,
le16_to_cpu(product_info->BootBuildNumber));
- dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0],
- product_info->ManufactureDescDate[1],
- product_info->ManufactureDescDate[2]+1900);
+ dbg(" FirmwareMajorVersion %d.%d.%d",
+ product_info->FirmwareMajorVersion,
+ product_info->FirmwareMinorVersion,
+ le16_to_cpu(product_info->FirmwareBuildNumber));
+ dbg(" ManufactureDescDate %d/%d/%d",
+ product_info->ManufactureDescDate[0],
+ product_info->ManufactureDescDate[1],
+ product_info->ManufactureDescDate[2]+1900);
dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);
dbg(" EpicVer %d", product_info->EpicVer);
}
@@ -444,55 +470,60 @@ static void get_product_info(struct edgeport_serial *edge_serial)
{
struct edgeport_product_info *product_info = &edge_serial->product_info;
- memset (product_info, 0, sizeof(struct edgeport_product_info));
-
- product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
- product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
- product_info->ProdInfoVer = 0;
-
- product_info->RomSize = edge_serial->manuf_descriptor.RomSize;
- product_info->RamSize = edge_serial->manuf_descriptor.RamSize;
- product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev;
- product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev;
-
- product_info->BootMajorVersion = edge_serial->boot_descriptor.MajorVersion;
- product_info->BootMinorVersion = edge_serial->boot_descriptor.MinorVersion;
- product_info->BootBuildNumber = edge_serial->boot_descriptor.BuildNumber;
-
- memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
-
- // check if this is 2nd generation hardware
- if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) {
- product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
- } else {
- product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
- }
-
- // Determine Product type and set appropriate flags
+ memset(product_info, 0, sizeof(struct edgeport_product_info));
+
+ product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
+ product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
+ product_info->ProdInfoVer = 0;
+
+ product_info->RomSize = edge_serial->manuf_descriptor.RomSize;
+ product_info->RamSize = edge_serial->manuf_descriptor.RamSize;
+ product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev;
+ product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev;
+
+ product_info->BootMajorVersion =
+ edge_serial->boot_descriptor.MajorVersion;
+ product_info->BootMinorVersion =
+ edge_serial->boot_descriptor.MinorVersion;
+ product_info->BootBuildNumber =
+ edge_serial->boot_descriptor.BuildNumber;
+
+ memcpy(product_info->ManufactureDescDate,
+ edge_serial->manuf_descriptor.DescDate,
+ sizeof(edge_serial->manuf_descriptor.DescDate));
+
+ /* check if this is 2nd generation hardware */
+ if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct)
+ & ION_DEVICE_ID_80251_NETCHIP)
+ product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
+ else
+ product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
+
+ /* Determine Product type and set appropriate flags */
switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) {
- case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
- case ION_DEVICE_ID_EDGEPORT_4T:
- case ION_DEVICE_ID_EDGEPORT_4:
- case ION_DEVICE_ID_EDGEPORT_2:
- case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
- case ION_DEVICE_ID_EDGEPORT_8:
- case ION_DEVICE_ID_EDGEPORT_421:
- case ION_DEVICE_ID_EDGEPORT_21:
- case ION_DEVICE_ID_EDGEPORT_2_DIN:
- case ION_DEVICE_ID_EDGEPORT_4_DIN:
- case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
- product_info->IsRS232 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
+ case ION_DEVICE_ID_EDGEPORT_4T:
+ case ION_DEVICE_ID_EDGEPORT_4:
+ case ION_DEVICE_ID_EDGEPORT_2:
+ case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
+ case ION_DEVICE_ID_EDGEPORT_8:
+ case ION_DEVICE_ID_EDGEPORT_421:
+ case ION_DEVICE_ID_EDGEPORT_21:
+ case ION_DEVICE_ID_EDGEPORT_2_DIN:
+ case ION_DEVICE_ID_EDGEPORT_4_DIN:
+ case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
+ product_info->IsRS232 = 1;
+ break;
- case ION_DEVICE_ID_EDGEPORT_2I: // Edgeport/2 RS422/RS485
- product_info->IsRS422 = 1;
- product_info->IsRS485 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_2I: /* Edgeport/2 RS422/RS485 */
+ product_info->IsRS422 = 1;
+ product_info->IsRS485 = 1;
+ break;
- case ION_DEVICE_ID_EDGEPORT_8I: // Edgeport/4 RS422
- case ION_DEVICE_ID_EDGEPORT_4I: // Edgeport/4 RS422
- product_info->IsRS422 = 1;
- break;
+ case ION_DEVICE_ID_EDGEPORT_8I: /* Edgeport/4 RS422 */
+ case ION_DEVICE_ID_EDGEPORT_4I: /* Edgeport/4 RS422 */
+ product_info->IsRS422 = 1;
+ break;
}
dump_product_info(product_info);
@@ -520,32 +551,32 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
ep->is_epic = 1;
memset(product_info, 0, sizeof(struct edgeport_product_info));
- product_info->NumPorts = epic->NumPorts;
- product_info->ProdInfoVer = 0;
- product_info->FirmwareMajorVersion = epic->MajorVersion;
- product_info->FirmwareMinorVersion = epic->MinorVersion;
- product_info->FirmwareBuildNumber = epic->BuildNumber;
- product_info->iDownloadFile = epic->iDownloadFile;
- product_info->EpicVer = epic->EpicVer;
- product_info->Epic = epic->Supports;
- product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
+ product_info->NumPorts = epic->NumPorts;
+ product_info->ProdInfoVer = 0;
+ product_info->FirmwareMajorVersion = epic->MajorVersion;
+ product_info->FirmwareMinorVersion = epic->MinorVersion;
+ product_info->FirmwareBuildNumber = epic->BuildNumber;
+ product_info->iDownloadFile = epic->iDownloadFile;
+ product_info->EpicVer = epic->EpicVer;
+ product_info->Epic = epic->Supports;
+ product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
dump_product_info(product_info);
bits = &ep->epic_descriptor.Supports;
dbg("**EPIC descriptor:");
dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE");
- dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE" );
- dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE" );
- dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE" );
- dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE" );
- dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE" );
- dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE" );
- dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE" );
- dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE" );
- dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE" );
- dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE" );
- dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE" );
- dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE" );
+ dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE");
+ dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE");
+ dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE");
+ dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE");
+ dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE");
+ dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE");
+ dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE");
+ dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE");
+ dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE");
+ dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE");
+ dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE");
+ dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE");
}
return result;
@@ -561,10 +592,10 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
/*****************************************************************************
* edge_interrupt_callback
- * this is the callback function for when we have received data on the
+ * this is the callback function for when we have received data on the
* interrupt endpoint.
*****************************************************************************/
-static void edge_interrupt_callback (struct urb *urb)
+static void edge_interrupt_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
struct edgeport_port *edge_port;
@@ -589,17 +620,17 @@ static void edge_interrupt_callback (struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __func__, status);
+ __func__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d",
- __func__, status);
+ dbg("%s - nonzero urb status received: %d", __func__, status);
goto exit;
}
- // process this interrupt-read even if there are no ports open
+ /* process this interrupt-read even if there are no ports open */
if (length) {
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+ __func__, length, data);
if (length > 1) {
bytes_avail = data[0] | (data[1] << 8);
@@ -613,7 +644,8 @@ static void edge_interrupt_callback (struct urb *urb)
dbg("%s - posting a read", __func__);
edge_serial->read_in_progress = true;
- /* we have pending bytes on the bulk in pipe, send a request */
+ /* we have pending bytes on the
+ bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev;
result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
@@ -627,7 +659,8 @@ static void edge_interrupt_callback (struct urb *urb)
/* grab the txcredits for the ports if available */
position = 2;
portNumber = 0;
- while ((position < length) && (portNumber < edge_serial->serial->num_ports)) {
+ while ((position < length) &&
+ (portNumber < edge_serial->serial->num_ports)) {
txCredits = data[position] | (data[position+1] << 8);
if (txCredits) {
port = edge_serial->serial->port[portNumber];
@@ -636,14 +669,19 @@ static void edge_interrupt_callback (struct urb *urb)
spin_lock(&edge_port->ep_lock);
edge_port->txCredits += txCredits;
spin_unlock(&edge_port->ep_lock);
- dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
-
- /* tell the tty driver that something has changed */
- if (edge_port->port->tty)
- tty_wakeup(edge_port->port->tty);
-
- // Since we have more credit, check if more data can be sent
- send_more_port_data(edge_serial, edge_port);
+ dbg("%s - txcredits for port%d = %d",
+ __func__, portNumber,
+ edge_port->txCredits);
+
+ /* tell the tty driver that something
+ has changed */
+ if (edge_port->port->port.tty)
+ tty_wakeup(edge_port->port->port.tty);
+
+ /* Since we have more credit, check
+ if more data can be sent */
+ send_more_port_data(edge_serial,
+ edge_port);
}
}
position += 2;
@@ -652,19 +690,20 @@ static void edge_interrupt_callback (struct urb *urb)
}
exit:
- result = usb_submit_urb (urb, GFP_ATOMIC);
- if (result) {
- dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
- }
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting control urb\n",
+ __func__, result);
}
/*****************************************************************************
* edge_bulk_in_callback
- * this is the callback function for when we have received data on the
+ * this is the callback function for when we have received data on the
* bulk in endpoint.
*****************************************************************************/
-static void edge_bulk_in_callback (struct urb *urb)
+static void edge_bulk_in_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -689,16 +728,18 @@ static void edge_bulk_in_callback (struct urb *urb)
raw_data_length = urb->actual_length;
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
+ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+ __func__, raw_data_length, data);
spin_lock(&edge_serial->es_lock);
/* decrement our rxBytes available by the number that we just got */
edge_serial->rxBytesAvail -= raw_data_length;
- dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
+ dbg("%s - Received = %d, rxBytesAvail %d", __func__,
+ raw_data_length, edge_serial->rxBytesAvail);
- process_rcvd_data (edge_serial, data, urb->actual_length);
+ process_rcvd_data(edge_serial, data, urb->actual_length);
/* check to see if there's any more data for us to read */
if (edge_serial->rxBytesAvail > 0) {
@@ -721,10 +762,10 @@ static void edge_bulk_in_callback (struct urb *urb)
/*****************************************************************************
* edge_bulk_out_data_callback
- * this is the callback function for when we have finished sending serial data
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending
+ * serial data on the bulk out endpoint.
*****************************************************************************/
-static void edge_bulk_out_data_callback (struct urb *urb)
+static void edge_bulk_out_data_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
struct tty_struct *tty;
@@ -737,27 +778,29 @@ static void edge_bulk_out_data_callback (struct urb *urb)
__func__, status);
}
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
if (tty && edge_port->open) {
- /* let the tty driver wakeup if it has a special write_wakeup function */
+ /* let the tty driver wakeup if it has a special
+ write_wakeup function */
tty_wakeup(tty);
}
- // Release the Write URB
+ /* Release the Write URB */
edge_port->write_in_progress = false;
- // Check if more data needs to be sent
- send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port);
+ /* Check if more data needs to be sent */
+ send_more_port_data((struct edgeport_serial *)
+ (usb_get_serial_data(edge_port->port->serial)), edge_port);
}
/*****************************************************************************
* BulkOutCmdCallback
- * this is the callback function for when we have finished sending a command
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending a
+ * command on the bulk out endpoint.
*****************************************************************************/
-static void edge_bulk_out_cmd_callback (struct urb *urb)
+static void edge_bulk_out_cmd_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
struct tty_struct *tty;
@@ -766,22 +809,24 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
dbg("%s", __func__);
atomic_dec(&CmdUrbs);
- dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ dbg("%s - FREE URB %p (outstanding %d)", __func__,
+ urb, atomic_read(&CmdUrbs));
/* clean up the transfer buffer */
kfree(urb->transfer_buffer);
/* Free the command urb */
- usb_free_urb (urb);
+ usb_free_urb(urb);
if (status) {
- dbg("%s - nonzero write bulk status received: %d", __func__, status);
+ dbg("%s - nonzero write bulk status received: %d",
+ __func__, status);
return;
}
/* Get pointer to tty */
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
/* tell the tty driver that something has changed */
if (tty && edge_port->open)
@@ -803,7 +848,8 @@ static void edge_bulk_out_cmd_callback (struct urb *urb)
* If successful, we return 0
* Otherwise we return a negative error number.
*****************************************************************************/
-static int edge_open (struct usb_serial_port *port, struct file * filp)
+static int edge_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct usb_serial *serial;
@@ -815,55 +861,62 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
if (edge_port == NULL)
return -ENODEV;
- if (port->tty)
- port->tty->low_latency = low_latency;
+ if (tty)
+ tty->low_latency = low_latency;
- /* see if we've set up our endpoint info yet (can't set it up in edge_startup
- as the structures were not set up at that time.) */
+ /* see if we've set up our endpoint info yet (can't set it up
+ in edge_startup as the structures were not set up at that time.) */
serial = port->serial;
edge_serial = usb_get_serial_data(serial);
- if (edge_serial == NULL) {
+ if (edge_serial == NULL)
return -ENODEV;
- }
if (edge_serial->interrupt_in_buffer == NULL) {
struct usb_serial_port *port0 = serial->port[0];
-
+
/* not set up yet, so do it now */
- edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
- edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
+ edge_serial->interrupt_in_buffer =
+ port0->interrupt_in_buffer;
+ edge_serial->interrupt_in_endpoint =
+ port0->interrupt_in_endpointAddress;
edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
- edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
+ edge_serial->bulk_in_endpoint =
+ port0->bulk_in_endpointAddress;
edge_serial->read_urb = port0->read_urb;
- edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
-
+ edge_serial->bulk_out_endpoint =
+ port0->bulk_out_endpointAddress;
+
/* set up our interrupt urb */
usb_fill_int_urb(edge_serial->interrupt_read_urb,
- serial->dev,
- usb_rcvintpipe(serial->dev,
- port0->interrupt_in_endpointAddress),
- port0->interrupt_in_buffer,
- edge_serial->interrupt_read_urb->transfer_buffer_length,
- edge_interrupt_callback, edge_serial,
- edge_serial->interrupt_read_urb->interval);
-
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ port0->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ edge_serial->interrupt_read_urb->transfer_buffer_length,
+ edge_interrupt_callback, edge_serial,
+ edge_serial->interrupt_read_urb->interval);
+
/* set up our bulk in urb */
usb_fill_bulk_urb(edge_serial->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port0->bulk_in_endpointAddress),
- port0->bulk_in_buffer,
- edge_serial->read_urb->transfer_buffer_length,
- edge_bulk_in_callback, edge_serial);
+ usb_rcvbulkpipe(serial->dev,
+ port0->bulk_in_endpointAddress),
+ port0->bulk_in_buffer,
+ edge_serial->read_urb->transfer_buffer_length,
+ edge_bulk_in_callback, edge_serial);
edge_serial->read_in_progress = false;
/* start interrupt read for this edgeport
- * this interrupt will continue as long as the edgeport is connected */
- response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+ * this interrupt will continue as long
+ * as the edgeport is connected */
+ response = usb_submit_urb(edge_serial->interrupt_read_urb,
+ GFP_KERNEL);
if (response) {
- dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
+ dev_err(&port->dev,
+ "%s - Error %d submitting control urb\n",
+ __func__, response);
}
}
-
+
/* initialize our wait queues */
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
@@ -871,26 +924,29 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
init_waitqueue_head(&edge_port->wait_command);
/* initialize our icount structure */
- memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+ memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
/* initialize our port settings */
- edge_port->txCredits = 0; /* Can't send any data yet */
- edge_port->shadowMCR = MCR_MASTER_IE; /* Must always set this bit to enable ints! */
+ edge_port->txCredits = 0; /* Can't send any data yet */
+ /* Must always set this bit to enable ints! */
+ edge_port->shadowMCR = MCR_MASTER_IE;
edge_port->chaseResponsePending = false;
/* send a open port command */
edge_port->openPending = true;
edge_port->open = false;
- response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+ response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
if (response < 0) {
- dev_err(&port->dev, "%s - error sending open port command\n", __func__);
+ dev_err(&port->dev, "%s - error sending open port command\n",
+ __func__);
edge_port->openPending = false;
return -ENODEV;
}
/* now wait for the port to be completely opened */
- wait_event_timeout(edge_port->wait_open, !edge_port->openPending, OPEN_TIMEOUT);
+ wait_event_timeout(edge_port->wait_open, !edge_port->openPending,
+ OPEN_TIMEOUT);
if (!edge_port->open) {
/* open timed out */
@@ -904,25 +960,26 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
edge_port->txfifo.tail = 0;
edge_port->txfifo.count = 0;
edge_port->txfifo.size = edge_port->maxTxCredits;
- edge_port->txfifo.fifo = kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+ edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL);
if (!edge_port->txfifo.fifo) {
dbg("%s - no memory", __func__);
- edge_close (port, filp);
+ edge_close(tty, port, filp);
return -ENOMEM;
}
/* Allocate a URB for the write */
- edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
+ edge_port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
edge_port->write_in_progress = false;
if (!edge_port->write_urb) {
dbg("%s - no memory", __func__);
- edge_close (port, filp);
+ edge_close(tty, port, filp);
return -ENOMEM;
}
- dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
+ dbg("%s(%d) - Initialize TX fifo to %d bytes",
+ __func__, port->number, edge_port->maxTxCredits);
dbg("%s exited", __func__);
@@ -948,27 +1005,28 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
int loop = 10;
while (1) {
- // Save Last credits
+ /* Save Last credits */
lastCredits = edge_port->txCredits;
- // Did we get our Chase response
+ /* Did we get our Chase response */
if (!edge_port->chaseResponsePending) {
dbg("%s - Got Chase Response", __func__);
- // did we get all of our credit back?
- if (edge_port->txCredits == edge_port->maxTxCredits ) {
+ /* did we get all of our credit back? */
+ if (edge_port->txCredits == edge_port->maxTxCredits) {
dbg("%s - Got all credits", __func__);
return;
}
}
- // Block the thread for a while
- prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ /* Block the thread for a while */
+ prepare_to_wait(&edge_port->wait_chase, &wait,
+ TASK_UNINTERRUPTIBLE);
schedule_timeout(timeout);
finish_wait(&edge_port->wait_chase, &wait);
if (lastCredits == edge_port->txCredits) {
- // No activity.. count down.
+ /* No activity.. count down. */
loop--;
if (loop == 0) {
edge_port->chaseResponsePending = false;
@@ -976,8 +1034,9 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
return;
}
} else {
- // Reset timeout value back to 10 seconds
- dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
+ /* Reset timeout value back to 10 seconds */
+ dbg("%s - Last %d, Current %d", __func__,
+ lastCredits, edge_port->txCredits);
loop = 10;
}
}
@@ -994,7 +1053,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
* 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
-static void block_until_tx_empty (struct edgeport_port *edge_port)
+static void block_until_tx_empty(struct edgeport_port *edge_port)
{
DEFINE_WAIT(wait);
struct TxFifo *fifo = &edge_port->txfifo;
@@ -1003,31 +1062,32 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
int loop = 30;
while (1) {
- // Save Last count
+ /* Save Last count */
lastCount = fifo->count;
- // Is the Edgeport Buffer empty?
+ /* Is the Edgeport Buffer empty? */
if (lastCount == 0) {
dbg("%s - TX Buffer Empty", __func__);
return;
}
- // Block the thread for a while
- prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ /* Block the thread for a while */
+ prepare_to_wait(&edge_port->wait_chase, &wait,
+ TASK_UNINTERRUPTIBLE);
schedule_timeout(timeout);
finish_wait(&edge_port->wait_chase, &wait);
dbg("%s wait", __func__);
if (lastCount == fifo->count) {
- // No activity.. count down.
+ /* No activity.. count down. */
loop--;
if (loop == 0) {
dbg("%s - TIMEOUT", __func__);
return;
}
} else {
- // Reset timeout value back to seconds
+ /* Reset timeout value back to seconds */
loop = 30;
}
}
@@ -1038,20 +1098,21 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
* edge_close
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void edge_close (struct usb_serial_port *port, struct file * filp)
+static void edge_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
int status;
dbg("%s - port %d", __func__, port->number);
-
+
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
- if ((edge_serial == NULL) || (edge_port == NULL))
+ if (edge_serial == NULL || edge_port == NULL)
return;
-
- // block until tx is empty
+
+ /* block until tx is empty */
block_until_tx_empty(edge_port);
edge_port->closePending = true;
@@ -1063,13 +1124,12 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->chaseResponsePending = true;
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
- if (status == 0) {
- // block until chase finished
+ status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0)
+ /* block until chase finished */
block_until_chase_response(edge_port);
- } else {
+ else
edge_port->chaseResponsePending = false;
- }
}
if ((!edge_serial->is_epic) ||
@@ -1077,10 +1137,10 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
(edge_serial->epic_descriptor.Supports.IOSPClose))) {
/* close the port */
dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0);
}
- //port->close = true;
+ /* port->close = true; */
edge_port->closePending = false;
edge_port->open = false;
edge_port->openPending = false;
@@ -1088,7 +1148,8 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
usb_kill_urb(edge_port->write_urb);
if (edge_port->write_urb) {
- /* if this urb had a transfer buffer already (old transfer) free it */
+ /* if this urb had a transfer buffer already
+ (old transfer) free it */
kfree(edge_port->write_urb->transfer_buffer);
usb_free_urb(edge_port->write_urb);
edge_port->write_urb = NULL;
@@ -1097,16 +1158,17 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->txfifo.fifo = NULL;
dbg("%s exited", __func__);
-}
+}
/*****************************************************************************
* SerialWrite
- * this function is called by the tty driver when data should be written to
- * the port.
- * If successful, we return the number of bytes written, otherwise we return
- * a negative error number.
+ * this function is called by the tty driver when data should be written
+ * to the port.
+ * If successful, we return the number of bytes written, otherwise we
+ * return a negative error number.
*****************************************************************************/
-static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct TxFifo *fifo;
@@ -1121,66 +1183,76 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
if (edge_port == NULL)
return -ENODEV;
- // get a pointer to the Tx fifo
+ /* get a pointer to the Tx fifo */
fifo = &edge_port->txfifo;
spin_lock_irqsave(&edge_port->ep_lock, flags);
- // calculate number of bytes to put in fifo
- copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
+ /* calculate number of bytes to put in fifo */
+ copySize = min((unsigned int)count,
+ (edge_port->txCredits - fifo->count));
- dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", __func__,
- port->number, count, edge_port->txCredits - fifo->count, copySize);
+ dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes",
+ __func__, port->number, count,
+ edge_port->txCredits - fifo->count, copySize);
- /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+ /* catch writes of 0 bytes which the tty driver likes to give us,
+ and when txCredits is empty */
if (copySize == 0) {
dbg("%s - copySize = Zero", __func__);
goto finish_write;
}
- // queue the data
- // since we can never overflow the buffer we do not have to check for full condition
-
- // the copy is done is two parts -- first fill to the end of the buffer
- // then copy the reset from the start of the buffer
-
+ /* queue the data
+ * since we can never overflow the buffer we do not have to check for a
+ * full condition
+ *
+ * the copy is done is two parts -- first fill to the end of the buffer
+ * then copy the reset from the start of the buffer
+ */
bytesleft = fifo->size - fifo->head;
- firsthalf = min (bytesleft, copySize);
- dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
+ firsthalf = min(bytesleft, copySize);
+ dbg("%s - copy %d bytes of %d into fifo ", __func__,
+ firsthalf, bytesleft);
/* now copy our data */
memcpy(&fifo->fifo[fifo->head], data, firsthalf);
- usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ firsthalf, &fifo->fifo[fifo->head]);
- // update the index and size
+ /* update the index and size */
fifo->head += firsthalf;
fifo->count += firsthalf;
- // wrap the index
- if (fifo->head == fifo->size) {
+ /* wrap the index */
+ if (fifo->head == fifo->size)
fifo->head = 0;
- }
secondhalf = copySize-firsthalf;
if (secondhalf) {
dbg("%s - copy rest of data %d", __func__, secondhalf);
memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
- usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
- // update the index and size
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ secondhalf, &fifo->fifo[fifo->head]);
+ /* update the index and size */
fifo->count += secondhalf;
fifo->head += secondhalf;
- // No need to check for wrap since we can not get to end of fifo in this part
+ /* No need to check for wrap since we can not get to end of
+ * the fifo in this part
+ */
}
finish_write:
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
+ send_more_port_data((struct edgeport_serial *)
+ usb_get_serial_data(port->serial), edge_port);
- dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
+ dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__,
+ copySize, edge_port->txCredits, fifo->count);
- return copySize;
+ return copySize;
}
@@ -1197,7 +1269,8 @@ finish_write:
* can transmit more.
*
************************************************************************/
-static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port)
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+ struct edgeport_port *edge_port)
{
struct TxFifo *fifo = &edge_port->txfifo;
struct urb *urb;
@@ -1216,67 +1289,78 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
if (edge_port->write_in_progress ||
!edge_port->open ||
(fifo->count == 0)) {
- dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+ dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d",
+ __func__, edge_port->port->number,
+ fifo->count, edge_port->write_in_progress);
goto exit_send;
}
- // since the amount of data in the fifo will always fit into the
- // edgeport buffer we do not need to check the write length
-
- // Do we have enough credits for this port to make it worthwhile
- // to bother queueing a write. If it's too small, say a few bytes,
- // it's better to wait for more credits so we can do a larger
- // write.
- if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
- dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
+ /* since the amount of data in the fifo will always fit into the
+ * edgeport buffer we do not need to check the write length
+ *
+ * Do we have enough credits for this port to make it worthwhile
+ * to bother queueing a write. If it's too small, say a few bytes,
+ * it's better to wait for more credits so we can do a larger write.
+ */
+ if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) {
+ dbg("%s(%d) Not enough credit - fifo %d TxCredit %d",
+ __func__, edge_port->port->number, fifo->count,
+ edge_port->txCredits);
goto exit_send;
}
- // lock this write
+ /* lock this write */
edge_port->write_in_progress = true;
- // get a pointer to the write_urb
+ /* get a pointer to the write_urb */
urb = edge_port->write_urb;
/* make sure transfer buffer is freed */
kfree(urb->transfer_buffer);
urb->transfer_buffer = NULL;
- /* build the data header for the buffer and port that we are about to send out */
+ /* build the data header for the buffer and port that we are about
+ to send out */
count = fifo->count;
- buffer = kmalloc (count+2, GFP_ATOMIC);
+ buffer = kmalloc(count+2, GFP_ATOMIC);
if (buffer == NULL) {
- dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
+ dev_err(&edge_port->port->dev,
+ "%s - no more kernel memory...\n", __func__);
edge_port->write_in_progress = false;
goto exit_send;
}
- buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count);
- buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count);
+ buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number
+ - edge_port->port->serial->minor, count);
+ buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number
+ - edge_port->port->serial->minor, count);
/* now copy our data */
bytesleft = fifo->size - fifo->tail;
- firsthalf = min (bytesleft, count);
+ firsthalf = min(bytesleft, count);
memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf);
fifo->tail += firsthalf;
fifo->count -= firsthalf;
- if (fifo->tail == fifo->size) {
+ if (fifo->tail == fifo->size)
fifo->tail = 0;
- }
secondhalf = count-firsthalf;
if (secondhalf) {
- memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf);
+ memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail],
+ secondhalf);
fifo->tail += secondhalf;
fifo->count -= secondhalf;
}
if (count)
- usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
+ usb_serial_debug_data(debug, &edge_port->port->dev,
+ __func__, count, &buffer[2]);
/* fill up the urb with all of our data and submit it */
- usb_fill_bulk_urb (urb, edge_serial->serial->dev,
- usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
- buffer, count+2, edge_bulk_out_data_callback, edge_port);
+ usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+ usb_sndbulkpipe(edge_serial->serial->dev,
+ edge_serial->bulk_out_endpoint),
+ buffer, count+2,
+ edge_bulk_out_data_callback, edge_port);
/* decrement the number of credits we have by the number we just sent */
edge_port->txCredits -= count;
@@ -1286,14 +1370,17 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
+ dev_err(&edge_port->port->dev,
+ "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
+ __func__, status);
edge_port->write_in_progress = false;
/* revert the credits as something bad happened. */
edge_port->txCredits += count;
edge_port->icount.tx -= count;
}
- dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
+ dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d",
+ __func__, count, edge_port->txCredits, fifo->count);
exit_send:
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1302,14 +1389,14 @@ exit_send:
/*****************************************************************************
* edge_write_room
- * this function is called by the tty driver when it wants to know how many
- * bytes of data we can accept for a specific port.
- * If successful, we return the amount of room that we have for this port
- * (the txCredits),
- * Otherwise we return a negative error number.
+ * this function is called by the tty driver when it wants to know how
+ * many bytes of data we can accept for a specific port. If successful,
+ * we return the amount of room that we have for this port (the txCredits)
+ * otherwise we return a negative error number.
*****************************************************************************/
-static int edge_write_room (struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room;
unsigned long flags;
@@ -1317,18 +1404,18 @@ static int edge_write_room (struct usb_serial_port *port)
dbg("%s", __func__);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->closePending)
- return -ENODEV;
+ return 0;
dbg("%s - port %d", __func__, port->number);
if (!edge_port->open) {
dbg("%s - port not opened", __func__);
- return -EINVAL;
+ return 0;
}
- // total of both buffers is still txCredit
+ /* total of both buffers is still txCredit */
spin_lock_irqsave(&edge_port->ep_lock, flags);
room = edge_port->txCredits - edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1340,15 +1427,16 @@ static int edge_write_room (struct usb_serial_port *port)
/*****************************************************************************
* edge_chars_in_buffer
- * this function is called by the tty driver when it wants to know how many
- * bytes of data we currently have outstanding in the port (data that has
- * been written, but hasn't made it out the port yet)
- * If successful, we return the number of bytes left to be written in the
- * system,
+ * this function is called by the tty driver when it wants to know how
+ * many bytes of data we currently have outstanding in the port (data that
+ * has been written, but hasn't made it out the port yet)
+ * If successful, we return the number of bytes left to be written in the
+ * system,
* Otherwise we return a negative error number.
*****************************************************************************/
-static int edge_chars_in_buffer (struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int num_chars;
unsigned long flags;
@@ -1356,20 +1444,22 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
dbg("%s", __func__);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->closePending)
- return -ENODEV;
+ return 0;
if (!edge_port->open) {
dbg("%s - port not opened", __func__);
- return -EINVAL;
+ return 0;
}
spin_lock_irqsave(&edge_port->ep_lock, flags);
- num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+ num_chars = edge_port->maxTxCredits - edge_port->txCredits +
+ edge_port->txfifo.count;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
if (num_chars) {
- dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
+ dbg("%s(port %d) - returns %d", __func__,
+ port->number, num_chars);
}
return num_chars;
@@ -1381,10 +1471,10 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
* this function is called by the tty driver when it wants to stop the data
* being read from the port.
*****************************************************************************/
-static void edge_throttle (struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1397,28 +1487,21 @@ static void edge_throttle (struct usb_serial_port *port)
return;
}
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = edge_write (port, &stop_char, 1);
- if (status <= 0) {
+ status = edge_write(tty, port, &stop_char, 1);
+ if (status <= 0)
return;
- }
}
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
edge_port->shadowMCR &= ~MCR_RTS;
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
+ status = send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
+ if (status != 0)
return;
- }
}
return;
@@ -1427,13 +1510,13 @@ static void edge_throttle (struct usb_serial_port *port)
/*****************************************************************************
* edge_unthrottle
- * this function is called by the tty driver when it wants to resume the data
- * being read from the port (called after SerialThrottle is called)
+ * this function is called by the tty driver when it wants to resume the
+ * data being read from the port (called after SerialThrottle is called)
*****************************************************************************/
-static void edge_unthrottle (struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -1446,43 +1529,31 @@ static void edge_unthrottle (struct usb_serial_port *port)
return;
}
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = edge_write (port, &start_char, 1);
- if (status <= 0) {
+ status = edge_write(tty, port, &start_char, 1);
+ if (status <= 0)
return;
- }
}
-
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
edge_port->shadowMCR |= MCR_RTS;
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
- return;
- }
+ send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
}
-
- return;
}
/*****************************************************************************
* SerialSetTermios
- * this function is called by the tty driver when it wants to change the termios structure
+ * this function is called by the tty driver when it wants to change
+ * the termios structure
*****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- /* FIXME: This function appears unused ?? */
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int cflag;
cflag = tty->termios->c_cflag;
@@ -1502,9 +1573,7 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
}
/* change the port settings to the new ones specified */
- change_port_settings (edge_port, old_termios);
-
- return;
+ change_port_settings(tty, edge_port, old_termios);
}
@@ -1516,9 +1585,10 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
* release the bus after transmitting. This must be done when
* the transmit shift register is empty, not be done when the
* transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
+ * allows an RS485 driver to be written in user space.
*****************************************************************************/
-static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value)
+static int get_lsr_info(struct edgeport_port *edge_port,
+ unsigned int __user *value)
{
unsigned int result = 0;
unsigned long flags;
@@ -1536,25 +1606,10 @@ static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *va
return 0;
}
-static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value)
-{
- unsigned int result = 0;
- struct tty_struct *tty = edge_port->port->tty;
-
- if (!tty)
- return -ENOIOCTLCMD;
-
- result = tty->read_cnt;
-
- dbg("%s(%d) = %d", __func__, edge_port->port->number, result);
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- //return 0;
- return -ENOIOCTLCMD;
-}
-
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
@@ -1582,8 +1637,9 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
return 0;
}
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr;
@@ -1606,7 +1662,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
+static int get_serial_info(struct edgeport_port *edge_port,
+ struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
@@ -1624,9 +1681,6 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
tmp.closing_wait = 30*HZ;
-// tmp.custom_divisor = state->custom_divisor;
-// tmp.hub6 = state->hub6;
-// tmp.io_type = state->io_type;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
@@ -1639,8 +1693,10 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
* SerialIoctl
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
DEFINE_WAIT(wait);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
@@ -1650,71 +1706,61 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
- // return number of bytes available
- case TIOCINQ:
- dbg("%s (%d) TIOCINQ", __func__, port->number);
- return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
- break;
-
- case TIOCSERGETLSR:
- dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return get_lsr_info(edge_port, (unsigned int __user *) arg);
- return 0;
-
- case TIOCGSERIAL:
- dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
- return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
- case TIOCSSERIAL:
- dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
-
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
- schedule();
- finish_wait(&edge_port->delta_msr_wait, &wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
+ case TIOCSERGETLSR:
+ dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
+ return get_lsr_info(edge_port, (unsigned int __user *) arg);
+
+ case TIOCGSERIAL:
+ dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(edge_port, (struct serial_struct __user *) arg);
+
+ case TIOCMIWAIT:
+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ prepare_to_wait(&edge_port->delta_msr_wait,
+ &wait, TASK_INTERRUPTIBLE);
+ schedule();
+ finish_wait(&edge_port->delta_msr_wait, &wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = edge_port->icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ return 0;
}
- /* NOTREACHED */
- break;
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+ break;
- case TIOCGICOUNT:
- cnow = edge_port->icount;
- memset(&icount, 0, sizeof(icount));
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, icount.rx, icount.tx );
- if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
- return -EFAULT;
- return 0;
+ case TIOCGICOUNT:
+ cnow = edge_port->icount;
+ memset(&icount, 0, sizeof(icount));
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+ dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+ __func__, port->number, icount.rx, icount.tx);
+ if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
}
-
return -ENOIOCTLCMD;
}
@@ -1723,8 +1769,9 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
* SerialBreak
* this function sends a break to the port
*****************************************************************************/
-static void edge_break (struct usb_serial_port *port, int break_state)
+static void edge_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
int status;
@@ -1736,9 +1783,9 @@ static void edge_break (struct usb_serial_port *port, int break_state)
edge_port->chaseResponsePending = true;
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
if (status == 0) {
- // block until chase finished
+ /* block until chase finished */
block_until_chase_response(edge_port);
} else {
edge_port->chaseResponsePending = false;
@@ -1750,14 +1797,16 @@ static void edge_break (struct usb_serial_port *port, int break_state)
(edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
if (break_state == -1) {
dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+ status = send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_BREAK, 0);
} else {
dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
- }
- if (status) {
- dbg("%s - error sending break set/clear command.", __func__);
+ status = send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_CLEAR_BREAK, 0);
}
+ if (status)
+ dbg("%s - error sending break set/clear command.",
+ __func__);
}
return;
@@ -1768,7 +1817,8 @@ static void edge_break (struct usb_serial_port *port, int break_state)
* process_rcvd_data
* this function handles the data received on the bulk in pipe.
*****************************************************************************/
-static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength)
+static void process_rcvd_data(struct edgeport_serial *edge_serial,
+ unsigned char *buffer, __u16 bufferLength)
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
@@ -1789,105 +1839,123 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
lastBufferLength = bufferLength;
switch (edge_serial->rxState) {
- case EXPECT_HDR1:
- edge_serial->rxHeader1 = *buffer;
- ++buffer;
- --bufferLength;
+ case EXPECT_HDR1:
+ edge_serial->rxHeader1 = *buffer;
+ ++buffer;
+ --bufferLength;
- if (bufferLength == 0) {
- edge_serial->rxState = EXPECT_HDR2;
+ if (bufferLength == 0) {
+ edge_serial->rxState = EXPECT_HDR2;
+ break;
+ }
+ /* otherwise, drop on through */
+ case EXPECT_HDR2:
+ edge_serial->rxHeader2 = *buffer;
+ ++buffer;
+ --bufferLength;
+
+ dbg("%s - Hdr1=%02X Hdr2=%02X", __func__,
+ edge_serial->rxHeader1, edge_serial->rxHeader2);
+ /* Process depending on whether this header is
+ * data or status */
+
+ if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
+ /* Decode this status header and go to
+ * EXPECT_HDR1 (if we can process the status
+ * with only 2 bytes), or go to EXPECT_HDR3 to
+ * get the third byte. */
+ edge_serial->rxPort =
+ IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ edge_serial->rxStatusCode =
+ IOSP_GET_STATUS_CODE(
+ edge_serial->rxHeader1);
+
+ if (!IOSP_STATUS_IS_2BYTE(
+ edge_serial->rxStatusCode)) {
+ /* This status needs additional bytes.
+ * Save what we have and then wait for
+ * more data.
+ */
+ edge_serial->rxStatusParam
+ = edge_serial->rxHeader2;
+ edge_serial->rxState = EXPECT_HDR3;
break;
}
- /* otherwise, drop on through */
-
- case EXPECT_HDR2:
- edge_serial->rxHeader2 = *buffer;
- ++buffer;
- --bufferLength;
-
- dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
-
- // Process depending on whether this header is
- // data or status
-
- if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
- // Decode this status header and goto EXPECT_HDR1 (if we
- // can process the status with only 2 bytes), or goto
- // EXPECT_HDR3 to get the third byte.
-
- edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
- edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1);
-
- if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) {
- // This status needs additional bytes. Save what we have
- // and then wait for more data.
- edge_serial->rxStatusParam = edge_serial->rxHeader2;
-
- edge_serial->rxState = EXPECT_HDR3;
- break;
- }
+ /* We have all the header bytes, process the
+ status now */
+ process_rcvd_status(edge_serial,
+ edge_serial->rxHeader2, 0);
+ edge_serial->rxState = EXPECT_HDR1;
+ break;
+ } else {
+ edge_serial->rxPort =
+ IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+ edge_serial->rxBytesRemaining =
+ IOSP_GET_HDR_DATA_LEN(
+ edge_serial->rxHeader1,
+ edge_serial->rxHeader2);
+ dbg("%s - Data for Port %u Len %u",
+ __func__,
+ edge_serial->rxPort,
+ edge_serial->rxBytesRemaining);
+
+ /* ASSERT(DevExt->RxPort < DevExt->NumPorts);
+ * ASSERT(DevExt->RxBytesRemaining <
+ * IOSP_MAX_DATA_LENGTH);
+ */
- // We have all the header bytes, process the status now
- process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0);
- edge_serial->rxState = EXPECT_HDR1;
+ if (bufferLength == 0) {
+ edge_serial->rxState = EXPECT_DATA;
break;
- } else {
- edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
- edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
-
- dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
-
- //ASSERT( DevExt->RxPort < DevExt->NumPorts );
- //ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
-
- if (bufferLength == 0 ) {
- edge_serial->rxState = EXPECT_DATA;
- break;
- }
- // Else, drop through
}
+ /* Else, drop through */
+ }
+ case EXPECT_DATA: /* Expect data */
+ if (bufferLength < edge_serial->rxBytesRemaining) {
+ rxLen = bufferLength;
+ /* Expect data to start next buffer */
+ edge_serial->rxState = EXPECT_DATA;
+ } else {
+ /* BufLen >= RxBytesRemaining */
+ rxLen = edge_serial->rxBytesRemaining;
+ /* Start another header next time */
+ edge_serial->rxState = EXPECT_HDR1;
+ }
- case EXPECT_DATA: // Expect data
-
- if (bufferLength < edge_serial->rxBytesRemaining) {
- rxLen = bufferLength;
- edge_serial->rxState = EXPECT_DATA; // Expect data to start next buffer
- } else {
- // BufLen >= RxBytesRemaining
- rxLen = edge_serial->rxBytesRemaining;
- edge_serial->rxState = EXPECT_HDR1; // Start another header next time
- }
+ bufferLength -= rxLen;
+ edge_serial->rxBytesRemaining -= rxLen;
- bufferLength -= rxLen;
- edge_serial->rxBytesRemaining -= rxLen;
-
- /* spit this data back into the tty driver if this port is open */
- if (rxLen) {
- port = edge_serial->serial->port[edge_serial->rxPort];
- edge_port = usb_get_serial_port_data(port);
- if (edge_port->open) {
- tty = edge_port->port->tty;
- if (tty) {
- dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
- edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
- }
- edge_port->icount.rx += rxLen;
+ /* spit this data back into the tty driver if this
+ port is open */
+ if (rxLen) {
+ port = edge_serial->serial->port[
+ edge_serial->rxPort];
+ edge_port = usb_get_serial_port_data(port);
+ if (edge_port->open) {
+ tty = edge_port->port->port.tty;
+ if (tty) {
+ dbg("%s - Sending %d bytes to TTY for port %d",
+ __func__, rxLen, edge_serial->rxPort);
+ edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
}
- buffer += rxLen;
+ edge_port->icount.rx += rxLen;
}
+ buffer += rxLen;
+ }
+ break;
- break;
-
- case EXPECT_HDR3: // Expect 3rd byte of status header
- edge_serial->rxHeader3 = *buffer;
- ++buffer;
- --bufferLength;
-
- // We have all the header bytes, process the status now
- process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3);
- edge_serial->rxState = EXPECT_HDR1;
- break;
-
+ case EXPECT_HDR3: /* Expect 3rd byte of status header */
+ edge_serial->rxHeader3 = *buffer;
+ ++buffer;
+ --bufferLength;
+
+ /* We have all the header bytes, process the
+ status now */
+ process_rcvd_status(edge_serial,
+ edge_serial->rxStatusParam,
+ edge_serial->rxHeader3);
+ edge_serial->rxState = EXPECT_HDR1;
+ break;
}
}
}
@@ -1895,9 +1963,11 @@ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned cha
/*****************************************************************************
* process_rcvd_status
- * this function handles the any status messages received on the bulk in pipe.
+ * this function handles the any status messages received on the
+ * bulk in pipe.
*****************************************************************************/
-static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3)
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+ __u8 byte2, __u8 byte3)
{
struct usb_serial_port *port;
struct edgeport_port *edge_port;
@@ -1907,7 +1977,9 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
port = edge_serial->serial->port[edge_serial->rxPort];
edge_port = usb_get_serial_port_data(port);
if (edge_port == NULL) {
- dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
+ dev_err(&edge_serial->serial->dev->dev,
+ "%s - edge_port == NULL for port %d\n",
+ __func__, edge_serial->rxPort);
return;
}
@@ -1915,22 +1987,28 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
if (code == IOSP_EXT_STATUS) {
switch (byte2) {
- case IOSP_EXT_STATUS_CHASE_RSP:
- // we want to do EXT status regardless of port open/closed
- dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
- // Currently, the only EXT_STATUS is Chase, so process here instead of one more call
- // to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
- // Also, we currently clear flag and close the port regardless of content of above's Byte3.
- // We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
- // like wait longer in block_until_chase_response, but for now we don't.
- edge_port->chaseResponsePending = false;
- wake_up (&edge_port->wait_chase);
- return;
+ case IOSP_EXT_STATUS_CHASE_RSP:
+ /* we want to do EXT status regardless of port
+ * open/closed */
+ dbg("%s - Port %u EXT CHASE_RSP Data = %02x",
+ __func__, edge_serial->rxPort, byte3);
+ /* Currently, the only EXT_STATUS is Chase, so process
+ * here instead of one more call to one more subroutine
+ * If/when more EXT_STATUS, there'll be more work to do
+ * Also, we currently clear flag and close the port
+ * regardless of content of above's Byte3.
+ * We could choose to do something else when Byte3 says
+ * Timeout on Chase from Edgeport, like wait longer in
+ * block_until_chase_response, but for now we don't.
+ */
+ edge_port->chaseResponsePending = false;
+ wake_up(&edge_port->wait_chase);
+ return;
- case IOSP_EXT_STATUS_RX_CHECK_RSP:
- dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
- //Port->RxCheckRsp = true;
- return;
+ case IOSP_EXT_STATUS_RX_CHECK_RSP:
+ dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3);
+ /* Port->RxCheckRsp = true; */
+ return;
}
}
@@ -1938,11 +2016,14 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
edge_port->maxTxCredits = edge_port->txCredits;
dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
- handle_new_msr (edge_port, byte2);
+ handle_new_msr(edge_port, byte2);
- /* send the current line settings to the port so we are in sync with any further termios calls */
- if (edge_port->port->tty)
- change_port_settings (edge_port, edge_port->port->tty->termios);
+ /* send the current line settings to the port so we are
+ in sync with any further termios calls */
+ /* FIXME: locking on tty */
+ if (edge_port->port->port.tty)
+ change_port_settings(edge_port->port->port.tty,
+ edge_port, edge_port->port->port.tty->termios);
/* we have completed the open */
edge_port->openPending = false;
@@ -1951,45 +2032,49 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
return;
}
- // If port is closed, silently discard all rcvd status. We can
- // have cases where buffered status is received AFTER the close
- // port command is sent to the Edgeport.
- if (!edge_port->open || edge_port->closePending) {
+ /* If port is closed, silently discard all rcvd status. We can
+ * have cases where buffered status is received AFTER the close
+ * port command is sent to the Edgeport.
+ */
+ if (!edge_port->open || edge_port->closePending)
return;
- }
switch (code) {
- // Not currently sent by Edgeport
- case IOSP_STATUS_LSR:
- dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
- handle_new_lsr(edge_port, false, byte2, 0);
- break;
+ /* Not currently sent by Edgeport */
+ case IOSP_STATUS_LSR:
+ dbg("%s - Port %u LSR Status = %02x",
+ __func__, edge_serial->rxPort, byte2);
+ handle_new_lsr(edge_port, false, byte2, 0);
+ break;
- case IOSP_STATUS_LSR_DATA:
- dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
- // byte2 is LSR Register
- // byte3 is broken data byte
- handle_new_lsr(edge_port, true, byte2, byte3);
- break;
- //
- // case IOSP_EXT_4_STATUS:
- // dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
- // break;
- //
- case IOSP_STATUS_MSR:
- dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
-
- // Process this new modem status and generate appropriate
- // events, etc, based on the new status. This routine
- // also saves the MSR in Port->ShadowMsr.
- handle_new_msr(edge_port, byte2);
- break;
+ case IOSP_STATUS_LSR_DATA:
+ dbg("%s - Port %u LSR Status = %02x, Data = %02x",
+ __func__, edge_serial->rxPort, byte2, byte3);
+ /* byte2 is LSR Register */
+ /* byte3 is broken data byte */
+ handle_new_lsr(edge_port, true, byte2, byte3);
+ break;
+ /*
+ * case IOSP_EXT_4_STATUS:
+ * dbg("%s - Port %u LSR Status = %02x Data = %02x",
+ * __func__, edge_serial->rxPort, byte2, byte3);
+ * break;
+ */
+ case IOSP_STATUS_MSR:
+ dbg("%s - Port %u MSR Status = %02x",
+ __func__, edge_serial->rxPort, byte2);
+ /*
+ * Process this new modem status and generate appropriate
+ * events, etc, based on the new status. This routine
+ * also saves the MSR in Port->ShadowMsr.
+ */
+ handle_new_msr(edge_port, byte2);
+ break;
- default:
- dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
- break;
+ default:
+ dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+ break;
}
-
return;
}
@@ -1998,7 +2083,8 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
* edge_tty_recv
* this function passes data on to the tty flip buffer
*****************************************************************************/
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length)
{
int cnt;
@@ -2007,7 +2093,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
if (cnt < length) {
dev_err(dev, "%s - dropping data, %d bytes lost\n",
__func__, length - cnt);
- if(cnt == 0)
+ if (cnt == 0)
break;
}
tty_insert_flip_string(tty, data, cnt);
@@ -2029,22 +2115,19 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
dbg("%s %02x", __func__, newMsr);
- if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
+ EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
icount = &edge_port->icount;
/* update input line counters */
- if (newMsr & EDGEPORT_MSR_DELTA_CTS) {
+ if (newMsr & EDGEPORT_MSR_DELTA_CTS)
icount->cts++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_DSR) {
+ if (newMsr & EDGEPORT_MSR_DELTA_DSR)
icount->dsr++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_CD) {
+ if (newMsr & EDGEPORT_MSR_DELTA_CD)
icount->dcd++;
- }
- if (newMsr & EDGEPORT_MSR_DELTA_RI) {
+ if (newMsr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- }
wake_up_interruptible(&edge_port->delta_msr_wait);
}
@@ -2059,42 +2142,41 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
* handle_new_lsr
* this function handles any change to the lsr register for a port.
*****************************************************************************/
-static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data)
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+ __u8 lsr, __u8 data)
{
- __u8 newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
- struct async_icount *icount;
+ __u8 newLsr = (__u8) (lsr & (__u8)
+ (LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ struct async_icount *icount;
dbg("%s - %02x", __func__, newLsr);
edge_port->shadowLSR = lsr;
if (newLsr & LSR_BREAK) {
- //
- // Parity and Framing errors only count if they
- // occur exclusive of a break being
- // received.
- //
+ /*
+ * Parity and Framing errors only count if they
+ * occur exclusive of a break being
+ * received.
+ */
newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
}
/* Place LSR data byte into Rx buffer */
- if (lsrData && edge_port->port->tty)
- edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
+ if (lsrData && edge_port->port->port.tty)
+ edge_tty_recv(&edge_port->port->dev,
+ edge_port->port->port.tty, &data, 1);
/* update input line counters */
icount = &edge_port->icount;
- if (newLsr & LSR_BREAK) {
+ if (newLsr & LSR_BREAK)
icount->brk++;
- }
- if (newLsr & LSR_OVER_ERR) {
+ if (newLsr & LSR_OVER_ERR)
icount->overrun++;
- }
- if (newLsr & LSR_PAR_ERR) {
+ if (newLsr & LSR_PAR_ERR)
icount->parity++;
- }
- if (newLsr & LSR_FRM_ERR) {
+ if (newLsr & LSR_FRM_ERR)
icount->frame++;
- }
return;
}
@@ -2102,12 +2184,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 l
/****************************************************************************
* sram_write
- * writes a number of bytes to the Edgeport device's sram starting at the
+ * writes a number of bytes to the Edgeport device's sram starting at the
* given address.
* If successful returns the number of bytes written, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data)
{
int result;
__u16 current_length;
@@ -2115,32 +2198,37 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, 64);
return -ENOMEM;
}
/* need to split these writes up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
- memcpy (transfer_buffer, data, current_length);
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM,
- 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+
+/* dbg("%s - writing %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ memcpy(transfer_buffer, data, current_length);
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_WRITE_RAM,
+ 0x40, addr, extAddr, transfer_buffer,
+ current_length, 300);
if (result < 0)
break;
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2152,40 +2240,45 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
* If successful returns the number of bytes written, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+ __u16 length, const __u8 *data)
{
int result;
__u16 current_length;
unsigned char *transfer_buffer;
-// dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+/* dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+ __func__, 64);
return -ENOMEM;
}
/* need to split these writes up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
- memcpy (transfer_buffer, data, current_length);
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM,
- 0x40, addr, extAddr, transfer_buffer, current_length, 300);
+/* dbg("%s - writing %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ memcpy(transfer_buffer, data, current_length);
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_WRITE_ROM, 0x40,
+ addr, extAddr,
+ transfer_buffer, current_length, 300);
if (result < 0)
break;
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2197,7 +2290,8 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
* If successful returns the number of bytes read, otherwise it returns
* a negative error number of the problem.
****************************************************************************/
-static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+static int rom_read(struct usb_serial *serial, __u16 extAddr,
+ __u16 addr, __u16 length, __u8 *data)
{
int result;
__u16 current_length;
@@ -2205,32 +2299,36 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
- transfer_buffer = kmalloc (64, GFP_KERNEL);
+ transfer_buffer = kmalloc(64, GFP_KERNEL);
if (!transfer_buffer) {
- dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+ dev_err(&serial->dev->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 64);
return -ENOMEM;
}
/* need to split these reads up into 64 byte chunks */
result = 0;
while (length > 0) {
- if (length > 64) {
+ if (length > 64)
current_length = 64;
- } else {
+ else
current_length = length;
- }
-// dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM,
- 0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+/* dbg("%s - %x, %x, %d", __func__,
+ extAddr, addr, current_length); */
+ result = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_READ_ROM,
+ 0xC0, addr, extAddr, transfer_buffer,
+ current_length, 300);
if (result < 0)
break;
- memcpy (data, transfer_buffer, current_length);
+ memcpy(data, transfer_buffer, current_length);
length -= current_length;
addr += current_length;
data += current_length;
- }
+ }
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return result;
}
@@ -2239,7 +2337,8 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
* send_iosp_ext_cmd
* Is used to send a IOSP message to the Edgeport device
****************************************************************************/
-static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param)
+static int send_iosp_ext_cmd(struct edgeport_port *edge_port,
+ __u8 command, __u8 param)
{
unsigned char *buffer;
unsigned char *currentCommand;
@@ -2248,19 +2347,20 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg("%s - %d, %d", __func__, command, param);
- buffer = kmalloc (10, GFP_ATOMIC);
+ buffer = kmalloc(10, GFP_ATOMIC);
if (!buffer) {
- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
+ dev_err(&edge_port->port->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 10);
return -ENOMEM;
}
currentCommand = buffer;
- MAKE_CMD_EXT_CMD (&currentCommand, &length,
- edge_port->port->number - edge_port->port->serial->minor,
- command, param);
+ MAKE_CMD_EXT_CMD(&currentCommand, &length,
+ edge_port->port->number - edge_port->port->serial->minor,
+ command, param);
- status = write_cmd_usb (edge_port, buffer, length);
+ status = write_cmd_usb(edge_port, buffer, length);
if (status) {
/* something bad happened, let's free up the memory */
kfree(buffer);
@@ -2274,43 +2374,50 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
* write_cmd_usb
* this function writes the given buffer out to the bulk write endpoint.
*****************************************************************************/
-static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length)
+static int write_cmd_usb(struct edgeport_port *edge_port,
+ unsigned char *buffer, int length)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
int status = 0;
struct urb *urb;
int timeout;
- usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+ usb_serial_debug_data(debug, &edge_port->port->dev,
+ __func__, length, buffer);
/* Allocate our next urb */
- urb = usb_alloc_urb (0, GFP_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
atomic_inc(&CmdUrbs);
- dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+ dbg("%s - ALLOCATE URB %p (outstanding %d)",
+ __func__, urb, atomic_read(&CmdUrbs));
- usb_fill_bulk_urb (urb, edge_serial->serial->dev,
- usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
- buffer, length, edge_bulk_out_cmd_callback, edge_port);
+ usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+ usb_sndbulkpipe(edge_serial->serial->dev,
+ edge_serial->bulk_out_endpoint),
+ buffer, length, edge_bulk_out_cmd_callback, edge_port);
edge_port->commandPending = true;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
+ dev_err(&edge_port->port->dev,
+ "%s - usb_submit_urb(write command) failed, status = %d\n",
+ __func__, status);
usb_kill_urb(urb);
usb_free_urb(urb);
atomic_dec(&CmdUrbs);
return status;
}
- // wait for command to finish
+ /* wait for command to finish */
timeout = COMMAND_TIMEOUT;
#if 0
- wait_event (&edge_port->wait_command, !edge_port->commandPending);
+ wait_event(&edge_port->wait_command, !edge_port->commandPending);
if (edge_port->commandPending) {
/* command timed out */
@@ -2327,15 +2434,18 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
* this function sends the proper command to change the baud rate of the
* specified port.
*****************************************************************************/
-static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate)
+static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+ int baudRate)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
int cmdLen = 0;
int divisor;
int status;
- unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
+ unsigned char number =
+ edge_port->port->number - edge_port->port->serial->minor;
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
@@ -2344,36 +2454,40 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
return 0;
}
- dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+ dbg("%s - port = %d, baud = %d", __func__,
+ edge_port->port->number, baudRate);
- status = calc_baud_rate_divisor (baudRate, &divisor);
+ status = calc_baud_rate_divisor(baudRate, &divisor);
if (status) {
- dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
+ dev_err(&edge_port->port->dev, "%s - bad baud rate\n",
+ __func__);
return status;
}
- // Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
+ /* Alloc memory for the string of commands. */
+ cmdBuffer = kmalloc(0x100, GFP_ATOMIC);
if (!cmdBuffer) {
- dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+ dev_err(&edge_port->port->dev,
+ "%s - kmalloc(%d) failed.\n", __func__, 0x100);
return -ENOMEM;
}
currCmd = cmdBuffer;
- // Enable access to divisor latch
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE );
+ /* Enable access to divisor latch */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE);
- // Write the divisor itself
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) );
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) );
+ /* Write the divisor itself */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLL, LOW8(divisor));
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLM, HIGH8(divisor));
- // Restore original value to disable access to divisor latch
- MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
+ /* Restore original value to disable access to divisor latch */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR,
+ edge_port->shadowLCR);
- status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+ status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
if (status) {
/* something bad happened, let's free up the memory */
- kfree (cmdBuffer);
+ kfree(cmdBuffer);
}
return status;
@@ -2385,7 +2499,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
* this function calculates the proper baud rate divisor for the specified
* baud rate.
*****************************************************************************/
-static int calc_baud_rate_divisor (int baudrate, int *divisor)
+static int calc_baud_rate_divisor(int baudrate, int *divisor)
{
int i;
__u16 custom;
@@ -2394,17 +2508,17 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
dbg("%s - %d", __func__, baudrate);
for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
- if ( divisor_table[i].BaudRate == baudrate ) {
+ if (divisor_table[i].BaudRate == baudrate) {
*divisor = divisor_table[i].Divisor;
return 0;
}
}
- // We have tried all of the standard baud rates
- // lets try to calculate the divisor for this baud rate
- // Make sure the baud rate is reasonable
+ /* We have tried all of the standard baud rates
+ * lets try to calculate the divisor for this baud rate
+ * Make sure the baud rate is reasonable */
if (baudrate > 50 && baudrate < 230400) {
- // get divisor
+ /* get divisor */
custom = (__u16)((230400L + baudrate/2) / baudrate);
*divisor = custom;
@@ -2419,17 +2533,20 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
/*****************************************************************************
* send_cmd_write_uart_register
- * this function builds up a uart register message and sends to to the device.
+ * this function builds up a uart register message and sends to to the device.
*****************************************************************************/
-static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue)
+static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
+ __u8 regNum, __u8 regValue)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
unsigned long cmdLen = 0;
int status;
- dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+ dbg("%s - write to %s register 0x%02x",
+ (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
@@ -2441,27 +2558,26 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
regNum == LCR) {
- dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
+ dbg("SendCmdWriteUartReg - Not writing to LCR Register");
return 0;
}
- // Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
- if (cmdBuffer == NULL ) {
+ /* Alloc memory for the string of commands. */
+ cmdBuffer = kmalloc(0x10, GFP_ATOMIC);
+ if (cmdBuffer == NULL)
return -ENOMEM;
- }
currCmd = cmdBuffer;
- // Build a cmd in the buffer to write the given register
- MAKE_CMD_WRITE_REG (&currCmd, &cmdLen,
- edge_port->port->number - edge_port->port->serial->minor,
- regNum, regValue);
+ /* Build a cmd in the buffer to write the given register */
+ MAKE_CMD_WRITE_REG(&currCmd, &cmdLen,
+ edge_port->port->number - edge_port->port->serial->minor,
+ regNum, regValue);
status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
if (status) {
/* something bad happened, let's free up the memory */
- kfree (cmdBuffer);
+ kfree(cmdBuffer);
}
return status;
@@ -2470,16 +2586,15 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
/*****************************************************************************
* change_port_settings
- * This routine is called to set the UART on the device to match the specified
- * new settings.
+ * This routine is called to set the UART on the device to match the
+ * specified new settings.
*****************************************************************************/
-#ifndef CMSPAR
-#define CMSPAR 0
-#endif
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
+
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port, struct ktermios *old_termios)
{
- struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
- struct tty_struct *tty;
+ struct edgeport_serial *edge_serial =
+ usb_get_serial_data(edge_port->port->serial);
int baud;
unsigned cflag;
__u8 mask = 0xff;
@@ -2498,21 +2613,26 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
return;
}
- tty = edge_port->port->tty;
- if ((!tty) ||
- (!tty->termios)) {
- dbg("%s - no tty structures", __func__);
- return;
- }
-
cflag = tty->termios->c_cflag;
switch (cflag & CSIZE) {
- case CS5: lData = LCR_BITS_5; mask = 0x1f; dbg("%s - data bits = 5", __func__); break;
- case CS6: lData = LCR_BITS_6; mask = 0x3f; dbg("%s - data bits = 6", __func__); break;
- case CS7: lData = LCR_BITS_7; mask = 0x7f; dbg("%s - data bits = 7", __func__); break;
- default:
- case CS8: lData = LCR_BITS_8; dbg("%s - data bits = 8", __func__); break;
+ case CS5:
+ lData = LCR_BITS_5; mask = 0x1f;
+ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ lData = LCR_BITS_6; mask = 0x3f;
+ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ lData = LCR_BITS_7; mask = 0x7f;
+ dbg("%s - data bits = 7", __func__);
+ break;
+ default:
+ case CS8:
+ lData = LCR_BITS_8;
+ dbg("%s - data bits = 8", __func__);
+ break;
}
lParity = LCR_PAR_NONE;
@@ -2554,7 +2674,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
dbg("%s - RTS/CTS is disabled", __func__);
}
- /* if we are implementing XON/XOFF, set the start and stop character in the device */
+ /* if we are implementing XON/XOFF, set the start and stop character
+ in the device */
if (I_IXOFF(tty) || I_IXON(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
unsigned char start_char = START_CHAR(tty);
@@ -2562,14 +2683,17 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
if ((!edge_serial->is_epic) ||
((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPSetXChar))) {
- send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
- send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+ send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_XON_CHAR, start_char);
+ send_iosp_ext_cmd(edge_port,
+ IOSP_CMD_SET_XOFF_CHAR, stop_char);
}
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
rxFlow |= IOSP_RX_FLOW_XON_XOFF;
- dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, start_char, stop_char);
} else {
dbg("%s - INBOUND XON/XOFF is disabled", __func__);
}
@@ -2577,7 +2701,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
/* if we are implementing OUTBOUND XON/XOFF */
if (I_IXON(tty)) {
txFlow |= IOSP_TX_FLOW_XON_XOFF;
- dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+ dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, start_char, stop_char);
} else {
dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
}
@@ -2600,20 +2725,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
edge_port->validDataMask = mask;
/* Send the updated LCR value to the EdgePort */
- status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR);
- if (status != 0) {
+ status = send_cmd_write_uart_register(edge_port, LCR,
+ edge_port->shadowLCR);
+ if (status != 0)
return;
- }
/* set up the MCR register and send it to the EdgePort */
edge_port->shadowMCR = MCR_MASTER_IE;
- if (cflag & CBAUD) {
+ if (cflag & CBAUD)
edge_port->shadowMCR |= (MCR_DTR | MCR_RTS);
- }
- status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
- if (status != 0) {
+
+ status = send_cmd_write_uart_register(edge_port, MCR,
+ edge_port->shadowMCR);
+ if (status != 0)
return;
- }
/* Determine divisor based on baud rate */
baud = tty_get_baud_rate(tty);
@@ -2623,7 +2748,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
}
dbg("%s - baud rate = %d", __func__, baud);
- status = send_cmd_write_baud_rate (edge_port, baud);
+ status = send_cmd_write_baud_rate(edge_port, baud);
if (status == -1) {
/* Speed change was not possible - put back the old speed */
baud = tty_termios_baud_rate(old_termios);
@@ -2640,7 +2765,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
* ASCII range, but it's only for debugging...
* NOTE: expects the unicode in LE format
****************************************************************************/
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size)
+static void unicode_to_ascii(char *string, int buflen,
+ __le16 *unicode, int unicode_size)
{
int i;
@@ -2659,75 +2785,99 @@ static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unic
/****************************************************************************
* get_manufacturing_desc
- * reads in the manufacturing descriptor and stores it into the serial
+ * reads in the manufacturing descriptor and stores it into the serial
* structure.
****************************************************************************/
-static void get_manufacturing_desc (struct edgeport_serial *edge_serial)
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
{
int response;
dbg("getting manufacturer descriptor");
- response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
- (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN,
- (__u8 *)(&edge_serial->manuf_descriptor));
+ response = rom_read(edge_serial->serial,
+ (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
+ (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff),
+ EDGE_MANUF_DESC_LEN,
+ (__u8 *)(&edge_serial->manuf_descriptor));
- if (response < 1) {
- dev_err(&edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n");
- } else {
+ if (response < 1)
+ dev_err(&edge_serial->serial->dev->dev,
+ "error in getting manufacturer descriptor\n");
+ else {
char string[30];
dbg("**Manufacturer Descriptor");
- dbg(" RomSize: %dK", edge_serial->manuf_descriptor.RomSize);
- dbg(" RamSize: %dK", edge_serial->manuf_descriptor.RamSize);
- dbg(" CpuRev: %d", edge_serial->manuf_descriptor.CpuRev);
- dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev);
- dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts);
- dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900);
+ dbg(" RomSize: %dK",
+ edge_serial->manuf_descriptor.RomSize);
+ dbg(" RamSize: %dK",
+ edge_serial->manuf_descriptor.RamSize);
+ dbg(" CpuRev: %d",
+ edge_serial->manuf_descriptor.CpuRev);
+ dbg(" BoardRev: %d",
+ edge_serial->manuf_descriptor.BoardRev);
+ dbg(" NumPorts: %d",
+ edge_serial->manuf_descriptor.NumPorts);
+ dbg(" DescDate: %d/%d/%d",
+ edge_serial->manuf_descriptor.DescDate[0],
+ edge_serial->manuf_descriptor.DescDate[1],
+ edge_serial->manuf_descriptor.DescDate[2]+1900);
unicode_to_ascii(string, sizeof(string),
- edge_serial->manuf_descriptor.SerialNumber,
- edge_serial->manuf_descriptor.SerNumLength/2);
+ edge_serial->manuf_descriptor.SerialNumber,
+ edge_serial->manuf_descriptor.SerNumLength/2);
dbg(" SerialNumber: %s", string);
unicode_to_ascii(string, sizeof(string),
- edge_serial->manuf_descriptor.AssemblyNumber,
- edge_serial->manuf_descriptor.AssemblyNumLength/2);
+ edge_serial->manuf_descriptor.AssemblyNumber,
+ edge_serial->manuf_descriptor.AssemblyNumLength/2);
dbg(" AssemblyNumber: %s", string);
unicode_to_ascii(string, sizeof(string),
edge_serial->manuf_descriptor.OemAssyNumber,
edge_serial->manuf_descriptor.OemAssyNumLength/2);
dbg(" OemAssyNumber: %s", string);
- dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType);
- dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid);
- dbg(" IonConfig: %d", edge_serial->manuf_descriptor.IonConfig);
+ dbg(" UartType: %d",
+ edge_serial->manuf_descriptor.UartType);
+ dbg(" IonPid: %d",
+ edge_serial->manuf_descriptor.IonPid);
+ dbg(" IonConfig: %d",
+ edge_serial->manuf_descriptor.IonConfig);
}
}
/****************************************************************************
* get_boot_desc
- * reads in the bootloader descriptor and stores it into the serial
+ * reads in the bootloader descriptor and stores it into the serial
* structure.
****************************************************************************/
-static void get_boot_desc (struct edgeport_serial *edge_serial)
+static void get_boot_desc(struct edgeport_serial *edge_serial)
{
int response;
dbg("getting boot descriptor");
- response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
- (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN,
- (__u8 *)(&edge_serial->boot_descriptor));
+ response = rom_read(edge_serial->serial,
+ (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
+ (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff),
+ EDGE_BOOT_DESC_LEN,
+ (__u8 *)(&edge_serial->boot_descriptor));
- if (response < 1) {
- dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
- } else {
+ if (response < 1)
+ dev_err(&edge_serial->serial->dev->dev,
+ "error in getting boot descriptor\n");
+ else {
dbg("**Boot Descriptor:");
- dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
- dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion);
- dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion);
- dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
- dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
- dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0);
- dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1);
+ dbg(" BootCodeLength: %d",
+ le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
+ dbg(" MajorVersion: %d",
+ edge_serial->boot_descriptor.MajorVersion);
+ dbg(" MinorVersion: %d",
+ edge_serial->boot_descriptor.MinorVersion);
+ dbg(" BuildNumber: %d",
+ le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
+ dbg(" Capabilities: 0x%x",
+ le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
+ dbg(" UConfig0: %d",
+ edge_serial->boot_descriptor.UConfig0);
+ dbg(" UConfig1: %d",
+ edge_serial->boot_descriptor.UConfig1);
}
}
@@ -2736,7 +2886,7 @@ static void get_boot_desc (struct edgeport_serial *edge_serial)
* load_application_firmware
* This is called to load the application firmware to the device
****************************************************************************/
-static void load_application_firmware (struct edgeport_serial *edge_serial)
+static void load_application_firmware(struct edgeport_serial *edge_serial)
{
const struct ihex_binrec *rec;
const struct firmware *fw;
@@ -2813,7 +2963,7 @@ static void load_application_firmware (struct edgeport_serial *edge_serial)
/****************************************************************************
* edge_startup
****************************************************************************/
-static int edge_startup (struct usb_serial *serial)
+static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -2855,10 +3005,10 @@ static int edge_startup (struct usb_serial *serial)
sizeof(struct edge_compatibility_bits));
/* get the manufacturing descriptor for this device */
- get_manufacturing_desc (edge_serial);
+ get_manufacturing_desc(edge_serial);
/* get the boot descriptor */
- get_boot_desc (edge_serial);
+ get_boot_desc(edge_serial);
get_product_info(edge_serial);
}
@@ -2879,41 +3029,43 @@ static int edge_startup (struct usb_serial *serial)
/* If not an EPiC device */
if (!edge_serial->is_epic) {
/* now load the application firmware into this device */
- load_application_firmware (edge_serial);
+ load_application_firmware(edge_serial);
dbg("%s - time 2 %ld", __func__, jiffies);
/* Check current Edgeport EEPROM and update if necessary */
- update_edgeport_E2PROM (edge_serial);
+ update_edgeport_E2PROM(edge_serial);
dbg("%s - time 3 %ld", __func__, jiffies);
/* set the configuration to use #1 */
-// dbg("set_configuration 1");
-// usb_set_configuration (dev, 1);
+/* dbg("set_configuration 1"); */
+/* usb_set_configuration (dev, 1); */
}
dbg(" FirmwareMajorVersion %d.%d.%d",
edge_serial->product_info.FirmwareMajorVersion,
edge_serial->product_info.FirmwareMinorVersion,
le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber));
- /* we set up the pointers to the endpoints in the edge_open function,
+ /* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */
/* set up our port private structures */
for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+ edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL);
if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
for (j = 0; j < i; ++j) {
- kfree (usb_get_serial_port_data(serial->port[j]));
- usb_set_serial_port_data(serial->port[j], NULL);
+ kfree(usb_get_serial_port_data(serial->port[j]));
+ usb_set_serial_port_data(serial->port[j],
+ NULL);
}
usb_set_serial_data(serial, NULL);
kfree(edge_serial);
return -ENOMEM;
}
- memset (edge_port, 0, sizeof(struct edgeport_port));
+ memset(edge_port, 0, sizeof(struct edgeport_port));
spin_lock_init(&edge_port->ep_lock);
edge_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], edge_port);
@@ -2922,14 +3074,16 @@ static int edge_startup (struct usb_serial *serial)
response = 0;
if (edge_serial->is_epic) {
- /* EPIC thing, set up our interrupt polling now and our read urb, so
- * that the device knows it really is connected. */
+ /* EPIC thing, set up our interrupt polling now and our read
+ * urb, so that the device knows it really is connected. */
interrupt_in_found = bulk_in_found = bulk_out_found = false;
- for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) {
+ for (i = 0; i < serial->interface->altsetting[0]
+ .desc.bNumEndpoints; ++i) {
struct usb_endpoint_descriptor *endpoint;
int buffer_size;
- endpoint = &serial->interface->altsetting[0].endpoint[i].desc;
+ endpoint = &serial->interface->altsetting[0].
+ endpoint[i].desc;
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
if (!interrupt_in_found &&
(usb_endpoint_is_int_in(endpoint))) {
@@ -2937,58 +3091,67 @@ static int edge_startup (struct usb_serial *serial)
dbg("found interrupt in");
/* not set up yet, so do it now */
- edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ edge_serial->interrupt_read_urb =
+ usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->interrupt_read_urb) {
err("out of memory");
return -ENOMEM;
}
- edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ edge_serial->interrupt_in_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) {
err("out of memory");
usb_free_urb(edge_serial->interrupt_read_urb);
return -ENOMEM;
}
- edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress;
+ edge_serial->interrupt_in_endpoint =
+ endpoint->bEndpointAddress;
/* set up our interrupt urb */
- usb_fill_int_urb(edge_serial->interrupt_read_urb,
- dev,
- usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- edge_serial->interrupt_in_buffer,
- buffer_size,
- edge_interrupt_callback,
- edge_serial,
- endpoint->bInterval);
+ usb_fill_int_urb(
+ edge_serial->interrupt_read_urb,
+ dev,
+ usb_rcvintpipe(dev,
+ endpoint->bEndpointAddress),
+ edge_serial->interrupt_in_buffer,
+ buffer_size,
+ edge_interrupt_callback,
+ edge_serial,
+ endpoint->bInterval);
interrupt_in_found = true;
}
if (!bulk_in_found &&
- (usb_endpoint_is_bulk_in(endpoint))) {
+ (usb_endpoint_is_bulk_in(endpoint))) {
/* we found a bulk in endpoint */
dbg("found bulk in");
/* not set up yet, so do it now */
- edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ edge_serial->read_urb =
+ usb_alloc_urb(0, GFP_KERNEL);
if (!edge_serial->read_urb) {
err("out of memory");
return -ENOMEM;
}
- edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ edge_serial->bulk_in_buffer =
+ kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) {
- err ("out of memory");
+ err("out of memory");
usb_free_urb(edge_serial->read_urb);
return -ENOMEM;
}
- edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress;
+ edge_serial->bulk_in_endpoint =
+ endpoint->bEndpointAddress;
/* set up our bulk in urb */
usb_fill_bulk_urb(edge_serial->read_urb, dev,
- usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
- edge_serial->bulk_in_buffer,
- le16_to_cpu(endpoint->wMaxPacketSize),
- edge_bulk_in_callback,
- edge_serial);
+ usb_rcvbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ edge_serial->bulk_in_buffer,
+ le16_to_cpu(endpoint->wMaxPacketSize),
+ edge_bulk_in_callback,
+ edge_serial);
bulk_in_found = true;
}
@@ -2996,21 +3159,24 @@ static int edge_startup (struct usb_serial *serial)
(usb_endpoint_is_bulk_out(endpoint))) {
/* we found a bulk out endpoint */
dbg("found bulk out");
- edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress;
+ edge_serial->bulk_out_endpoint =
+ endpoint->bEndpointAddress;
bulk_out_found = true;
}
}
if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
- err ("Error - the proper endpoints were not found!");
+ err("Error - the proper endpoints were not found!");
return -ENODEV;
}
/* start interrupt read for this edgeport this interrupt will
* continue as long as the edgeport is connected */
- response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+ response = usb_submit_urb(edge_serial->interrupt_read_urb,
+ GFP_KERNEL);
if (response)
- err("%s - Error %d submitting control urb", __func__, response);
+ err("%s - Error %d submitting control urb",
+ __func__, response);
}
return response;
}
@@ -3020,7 +3186,7 @@ static int edge_startup (struct usb_serial *serial)
* edge_shutdown
* This function is called whenever the device is removed from the usb bus.
****************************************************************************/
-static void edge_shutdown (struct usb_serial *serial)
+static void edge_shutdown(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
int i;
@@ -3028,8 +3194,8 @@ static void edge_shutdown (struct usb_serial *serial)
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
- kfree (usb_get_serial_port_data(serial->port[i]));
+ for (i = 0; i < serial->num_ports; ++i) {
+ kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
/* free up our endpoint stuff */
@@ -3069,7 +3235,7 @@ static int __init edgeport_init(void)
if (retval)
goto failed_epic_device_register;
retval = usb_register(&io_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
atomic_set(&CmdUrbs, 0);
info(DRIVER_DESC " " DRIVER_VERSION);
@@ -3094,19 +3260,19 @@ failed_2port_device_register:
****************************************************************************/
static void __exit edgeport_exit (void)
{
- usb_deregister (&io_driver);
- usb_serial_deregister (&edgeport_2port_device);
- usb_serial_deregister (&edgeport_4port_device);
- usb_serial_deregister (&edgeport_8port_device);
- usb_serial_deregister (&epic_device);
+ usb_deregister(&io_driver);
+ usb_serial_deregister(&edgeport_2port_device);
+ usb_serial_deregister(&edgeport_4port_device);
+ usb_serial_deregister(&edgeport_8port_device);
+ usb_serial_deregister(&epic_device);
}
module_init(edgeport_init);
module_exit(edgeport_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("edgeport/boot.fw");
MODULE_FIRMWARE("edgeport/boot2.fw");
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 2ec85893f27..7eb9d67b81b 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -8,7 +8,7 @@
* 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.
- *
+ *
*/
#ifndef IO_TABLES_H
@@ -90,10 +90,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) },
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) },
{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) },
- { } /* Terminating entry */
+ { } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver io_driver = {
.name = "io_edgeport",
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 61daea3f7b2..cb4c54316cf 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -18,8 +18,8 @@
*
* Version history:
*
- * July 11, 2002 Removed 4 port device structure since all TI UMP
- * chips have only 2 ports
+ * July 11, 2002 Removed 4 port device structure since all TI UMP
+ * chips have only 2 ports
* David Iacovelli (davidi@ionetworks.com)
*
*/
@@ -38,7 +38,7 @@
#include <linux/serial.h>
#include <linux/ioctl.h>
#include <linux/firmware.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -57,18 +57,19 @@
struct edgeport_uart_buf_desc {
- __u32 count; // Number of bytes currently in buffer
+ __u32 count; /* Number of bytes currently in buffer */
};
/* different hardware types */
#define HARDWARE_TYPE_930 0
#define HARDWARE_TYPE_TIUMP 1
-// IOCTL_PRIVATE_TI_GET_MODE Definitions
-#define TI_MODE_CONFIGURING 0 // Device has not entered start device
-#define TI_MODE_BOOT 1 // Staying in boot mode
-#define TI_MODE_DOWNLOAD 2 // Made it to download mode
-#define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode
+/* IOCTL_PRIVATE_TI_GET_MODE Definitions */
+#define TI_MODE_CONFIGURING 0 /* Device has not entered start device */
+#define TI_MODE_BOOT 1 /* Staying in boot mode */
+#define TI_MODE_DOWNLOAD 2 /* Made it to download mode */
+#define TI_MODE_TRANSITIONING 3 /* Currently in boot mode but
+ transitioning to download mode */
/* read urb state */
#define EDGE_READ_URB_RUNNING 0
@@ -82,10 +83,9 @@ struct edgeport_uart_buf_desc {
/* Product information read from the Edgeport */
-struct product_info
-{
- int TiMode; // Current TI Mode
- __u8 hardware_type; // Type of hardware
+struct product_info {
+ int TiMode; /* Current TI Mode */
+ __u8 hardware_type; /* Type of hardware */
} __attribute__((packed));
/* circular buffer */
@@ -116,7 +116,7 @@ struct edgeport_port {
happen */
struct edgeport_serial *edge_serial;
struct usb_serial_port *port;
- __u8 bUartMode; /* Port type, 0: RS232, etc. */
+ __u8 bUartMode; /* Port type, 0: RS232, etc. */
spinlock_t ep_lock;
int ep_read_urb_state;
int ep_write_urb_in_use;
@@ -125,8 +125,9 @@ struct edgeport_port {
struct edgeport_serial {
struct product_info product_info;
- u8 TI_I2C_Type; // Type of I2C in UMP
- u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode
+ u8 TI_I2C_Type; /* Type of I2C in UMP */
+ u8 TiReadI2C; /* Set to TRUE if we have read the
+ I2c in Boot Mode */
struct mutex es_lock;
int num_ports_open;
struct usb_serial *serial;
@@ -214,7 +215,7 @@ static struct usb_device_id id_table_combined [] = {
{ }
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver io_driver = {
.name = "io_ti",
@@ -231,20 +232,20 @@ static unsigned short OperationalBuildNumber;
static int debug;
-static int TIStayInBootMode = 0;
static int low_latency = EDGE_LOW_LATENCY;
static int closing_wait = EDGE_CLOSING_WAIT;
-static int ignore_cpu_rev = 0;
-static int default_uart_mode = 0; /* RS232 */
-
+static int ignore_cpu_rev;
+static int default_uart_mode; /* RS232 */
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length);
static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static void edge_send(struct usb_serial_port *port);
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static void edge_send(struct tty_struct *tty);
/* sysfs attributes */
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -262,87 +263,57 @@ static unsigned int edge_buf_get(struct edge_buf *eb, char *buf,
unsigned int count);
-static int TIReadVendorRequestSync (struct usb_device *dev,
- __u8 request,
- __u16 value,
- __u16 index,
- u8 *data,
- int size)
+static int ti_vread_sync(struct usb_device *dev, __u8 request,
+ __u16 value, __u16 index, u8 *data, int size)
{
int status;
- status = usb_control_msg (dev,
- usb_rcvctrlpipe(dev, 0),
- request,
- (USB_TYPE_VENDOR |
- USB_RECIP_DEVICE |
- USB_DIR_IN),
- value,
- index,
- data,
- size,
- 1000);
+ status = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
+ value, index, data, size, 1000);
if (status < 0)
return status;
if (status != size) {
- dbg ("%s - wanted to write %d, but only wrote %d",
- __func__, size, status);
+ dbg("%s - wanted to write %d, but only wrote %d",
+ __func__, size, status);
return -ECOMM;
}
return 0;
}
-static int TISendVendorRequestSync (struct usb_device *dev,
- __u8 request,
- __u16 value,
- __u16 index,
- u8 *data,
- int size)
+static int ti_vsend_sync(struct usb_device *dev, __u8 request,
+ __u16 value, __u16 index, u8 *data, int size)
{
int status;
- status = usb_control_msg (dev,
- usb_sndctrlpipe(dev, 0),
- request,
- (USB_TYPE_VENDOR |
- USB_RECIP_DEVICE |
- USB_DIR_OUT),
- value,
- index,
- data,
- size,
- 1000);
+ status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
+ value, index, data, size, 1000);
if (status < 0)
return status;
if (status != size) {
- dbg ("%s - wanted to write %d, but only wrote %d",
+ dbg("%s - wanted to write %d, but only wrote %d",
__func__, size, status);
return -ECOMM;
}
return 0;
}
-static int TIWriteCommandSync (struct usb_device *dev, __u8 command,
+static int send_cmd(struct usb_device *dev, __u8 command,
__u8 moduleid, __u16 value, u8 *data,
int size)
{
- return TISendVendorRequestSync (dev,
- command, // Request
- value, // wValue
- moduleid, // wIndex
- data, // TransferBuffer
- size); // TransferBufferLength
-
+ return ti_vsend_sync(dev, command, value, moduleid, data, size);
}
/* clear tx/rx buffers and fifo in TI UMP */
-static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
+static int purge_port(struct usb_serial_port *port, __u16 mask)
{
int port_number = port->number - port->serial->minor;
- dbg ("%s - port %d, mask %x", __func__, port_number, mask);
+ dbg("%s - port %d, mask %x", __func__, port_number, mask);
- return TIWriteCommandSync (port->serial->dev,
+ return send_cmd(port->serial->dev,
UMPC_PURGE_PORT,
(__u8)(UMPM_UART1_PORT + port_number),
mask,
@@ -351,92 +322,87 @@ static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
}
/**
- * TIReadDownloadMemory - Read edgeport memory from TI chip
+ * read_download_mem - Read edgeport memory from TI chip
* @dev: usb device pointer
* @start_address: Device CPU address at which to read
* @length: Length of above data
* @address_type: Can read both XDATA and I2C
* @buffer: pointer to input data buffer
*/
-static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+static int read_download_mem(struct usb_device *dev, int start_address,
int length, __u8 address_type, __u8 *buffer)
{
int status = 0;
__u8 read_length;
__be16 be_start_address;
-
- dbg ("%s - @ %x for %d", __func__, start_address, length);
+
+ dbg("%s - @ %x for %d", __func__, start_address, length);
/* Read in blocks of 64 bytes
* (TI firmware can't handle more than 64 byte reads)
*/
while (length) {
if (length > 64)
- read_length= 64;
+ read_length = 64;
else
read_length = (__u8)length;
if (read_length > 1) {
- dbg ("%s - @ %x for %d", __func__,
+ dbg("%s - @ %x for %d", __func__,
start_address, read_length);
}
- be_start_address = cpu_to_be16 (start_address);
- status = TIReadVendorRequestSync (dev,
- UMPC_MEMORY_READ, // Request
- (__u16)address_type, // wValue (Address type)
- (__force __u16)be_start_address, // wIndex (Address to read)
- buffer, // TransferBuffer
- read_length); // TransferBufferLength
+ be_start_address = cpu_to_be16(start_address);
+ status = ti_vread_sync(dev, UMPC_MEMORY_READ,
+ (__u16)address_type,
+ (__force __u16)be_start_address,
+ buffer, read_length);
if (status) {
- dbg ("%s - ERROR %x", __func__, status);
+ dbg("%s - ERROR %x", __func__, status);
return status;
}
- if (read_length > 1) {
+ if (read_length > 1)
usb_serial_debug_data(debug, &dev->dev, __func__,
read_length, buffer);
- }
/* Update pointers/length */
start_address += read_length;
buffer += read_length;
length -= read_length;
}
-
+
return status;
}
-static int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer)
+static int read_ram(struct usb_device *dev, int start_address,
+ int length, __u8 *buffer)
{
- return TIReadDownloadMemory (dev,
- start_address,
- length,
- DTK_ADDR_SPACE_XDATA,
- buffer);
+ return read_download_mem(dev, start_address, length,
+ DTK_ADDR_SPACE_XDATA, buffer);
}
/* Read edgeport memory to a given block */
-static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer)
+static int read_boot_mem(struct edgeport_serial *serial,
+ int start_address, int length, __u8 *buffer)
{
int status = 0;
int i;
- for (i=0; i< length; i++) {
- status = TIReadVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_READ, // Request
- serial->TI_I2C_Type, // wValue (Address type)
- (__u16)(start_address+i), // wIndex
- &buffer[i], // TransferBuffer
- 0x01); // TransferBufferLength
+ for (i = 0; i < length; i++) {
+ status = ti_vread_sync(serial->serial->dev,
+ UMPC_MEMORY_READ, serial->TI_I2C_Type,
+ (__u16)(start_address+i), &buffer[i], 0x01);
if (status) {
- dbg ("%s - ERROR %x", __func__, status);
+ dbg("%s - ERROR %x", __func__, status);
return status;
}
}
- dbg ("%s - start_address = %x, length = %d", __func__, start_address, length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+ dbg("%s - start_address = %x, length = %d",
+ __func__, start_address, length);
+ usb_serial_debug_data(debug, &serial->serial->dev->dev,
+ __func__, length, buffer);
serial->TiReadI2C = 1;
@@ -444,7 +410,8 @@ static int TIReadBootMemory (struct edgeport_serial *serial, int start_address,
}
/* Write given block to TI EPROM memory */
-static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int write_boot_mem(struct edgeport_serial *serial,
+ int start_address, int length, __u8 *buffer)
{
int status = 0;
int i;
@@ -452,57 +419,58 @@ static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address,
/* Must do a read before write */
if (!serial->TiReadI2C) {
- status = TIReadBootMemory(serial, 0, 1, &temp);
+ status = read_boot_mem(serial, 0, 1, &temp);
if (status)
return status;
}
- for (i=0; i < length; ++i) {
- status = TISendVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_WRITE, // Request
- buffer[i], // wValue
- (__u16)(i+start_address), // wIndex
- NULL, // TransferBuffer
- 0); // TransferBufferLength
+ for (i = 0; i < length; ++i) {
+ status = ti_vsend_sync(serial->serial->dev,
+ UMPC_MEMORY_WRITE, buffer[i],
+ (__u16)(i + start_address), NULL, 0);
if (status)
return status;
}
- dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+ dbg("%s - start_sddr = %x, length = %d",
+ __func__, start_address, length);
+ usb_serial_debug_data(debug, &serial->serial->dev->dev,
+ __func__, length, buffer);
return status;
}
/* Write edgeport I2C memory to TI chip */
-static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer)
+static int write_i2c_mem(struct edgeport_serial *serial,
+ int start_address, int length, __u8 address_type, __u8 *buffer)
{
int status = 0;
int write_length;
__be16 be_start_address;
/* We can only send a maximum of 1 aligned byte page at a time */
-
+
/* calulate the number of bytes left in the first page */
- write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1));
+ write_length = EPROM_PAGE_SIZE -
+ (start_address & (EPROM_PAGE_SIZE - 1));
if (write_length > length)
write_length = length;
- dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+ dbg("%s - BytesInFirstPage Addr = %x, length = %d",
+ __func__, start_address, write_length);
+ usb_serial_debug_data(debug, &serial->serial->dev->dev,
+ __func__, write_length, buffer);
/* Write first page */
- be_start_address = cpu_to_be16 (start_address);
- status = TISendVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_WRITE, // Request
- (__u16)address_type, // wValue
- (__force __u16)be_start_address, // wIndex
- buffer, // TransferBuffer
- write_length);
+ be_start_address = cpu_to_be16(start_address);
+ status = ti_vsend_sync(serial->serial->dev,
+ UMPC_MEMORY_WRITE, (__u16)address_type,
+ (__force __u16)be_start_address,
+ buffer, write_length);
if (status) {
- dbg ("%s - ERROR %d", __func__, status);
+ dbg("%s - ERROR %d", __func__, status);
return status;
}
@@ -510,29 +478,31 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
start_address += write_length;
buffer += write_length;
- /* We should be aligned now -- can write max page size bytes at a time */
+ /* We should be aligned now -- can write
+ max page size bytes at a time */
while (length) {
if (length > EPROM_PAGE_SIZE)
write_length = EPROM_PAGE_SIZE;
else
write_length = length;
- dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length);
- usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+ dbg("%s - Page Write Addr = %x, length = %d",
+ __func__, start_address, write_length);
+ usb_serial_debug_data(debug, &serial->serial->dev->dev,
+ __func__, write_length, buffer);
/* Write next page */
- be_start_address = cpu_to_be16 (start_address);
- status = TISendVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_WRITE, // Request
- (__u16)address_type, // wValue
- (__force __u16)be_start_address, // wIndex
- buffer, // TransferBuffer
- write_length); // TransferBufferLength
+ be_start_address = cpu_to_be16(start_address);
+ status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+ (__u16)address_type,
+ (__force __u16)be_start_address,
+ buffer, write_length);
if (status) {
- dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status);
+ dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n",
+ __func__, status);
return status;
}
-
+
length -= write_length;
start_address += write_length;
buffer += write_length;
@@ -541,25 +511,25 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
}
/* Examine the UMP DMA registers and LSR
- *
+ *
* Check the MSBit of the X and Y DMA byte count registers.
* A zero in this bit indicates that the TX DMA buffers are empty
* then check the TX Empty bit in the UART.
*/
-static int TIIsTxActive (struct edgeport_port *port)
+static int tx_active(struct edgeport_port *port)
{
int status;
struct out_endpoint_desc_block *oedb;
__u8 *lsr;
int bytes_left = 0;
- oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
+ oedb = kmalloc(sizeof(*oedb), GFP_KERNEL);
if (!oedb) {
- dev_err (&port->port->dev, "%s - out of memory\n", __func__);
+ dev_err(&port->port->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
- lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte,
+ lsr = kmalloc(1, GFP_KERNEL); /* Sigh, that's right, just one byte,
as not all platforms can do DMA
from stack */
if (!lsr) {
@@ -567,51 +537,47 @@ static int TIIsTxActive (struct edgeport_port *port)
return -ENOMEM;
}
/* Read the DMA Count Registers */
- status = TIReadRam (port->port->serial->dev,
- port->dma_address,
- sizeof( *oedb),
- (void *)oedb);
-
+ status = read_ram(port->port->serial->dev, port->dma_address,
+ sizeof(*oedb), (void *)oedb);
if (status)
goto exit_is_tx_active;
- dbg ("%s - XByteCount 0x%X", __func__, oedb->XByteCount);
+ dbg("%s - XByteCount 0x%X", __func__, oedb->XByteCount);
/* and the LSR */
- status = TIReadRam (port->port->serial->dev,
- port->uart_base + UMPMEM_OFFS_UART_LSR,
- 1,
- lsr);
+ status = read_ram(port->port->serial->dev,
+ port->uart_base + UMPMEM_OFFS_UART_LSR, 1, lsr);
if (status)
goto exit_is_tx_active;
- dbg ("%s - LSR = 0x%X", __func__, *lsr);
-
+ dbg("%s - LSR = 0x%X", __func__, *lsr);
+
/* If either buffer has data or we are transmitting then return TRUE */
- if ((oedb->XByteCount & 0x80 ) != 0 )
+ if ((oedb->XByteCount & 0x80) != 0)
bytes_left += 64;
- if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 )
+ if ((*lsr & UMP_UART_LSR_TX_MASK) == 0)
bytes_left += 1;
/* We return Not Active if we get any kind of error */
exit_is_tx_active:
- dbg ("%s - return %d", __func__, bytes_left );
+ dbg("%s - return %d", __func__, bytes_left);
kfree(lsr);
kfree(oedb);
return bytes_left;
}
-static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush)
+static void chase_port(struct edgeport_port *port, unsigned long timeout,
+ int flush)
{
int baud_rate;
- struct tty_struct *tty = port->port->tty;
+ struct tty_struct *tty = port->port->port.tty;
wait_queue_t wait;
unsigned long flags;
if (!timeout)
- timeout = (HZ*EDGE_CLOSING_WAIT)/100;
+ timeout = (HZ * EDGE_CLOSING_WAIT)/100;
/* wait for data to drain from the buffer */
spin_lock_irqsave(&port->ep_lock, flags);
@@ -621,7 +587,8 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
set_current_state(TASK_INTERRUPTIBLE);
if (edge_buf_data_avail(port->ep_out_buf) == 0
|| timeout == 0 || signal_pending(current)
- || !usb_get_intfdata(port->port->serial->interface)) /* disconnect */
+ || !usb_get_intfdata(port->port->serial->interface))
+ /* disconnect */
break;
spin_unlock_irqrestore(&port->ep_lock, flags);
timeout = schedule_timeout(timeout);
@@ -636,8 +603,9 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
/* wait for data to drain from the device */
timeout += jiffies;
while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
- && usb_get_intfdata(port->port->serial->interface)) { /* not disconnected */
- if (!TIIsTxActive(port))
+ && usb_get_intfdata(port->port->serial->interface)) {
+ /* not disconnected */
+ if (!tx_active(port))
break;
msleep(10);
}
@@ -647,72 +615,72 @@ static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int f
return;
/* wait one more character time, based on baud rate */
- /* (TIIsTxActive doesn't seem to wait for the last byte) */
- if ((baud_rate=port->baud_rate) == 0)
+ /* (tx_active doesn't seem to wait for the last byte) */
+ baud_rate = port->baud_rate;
+ if (baud_rate == 0)
baud_rate = 50;
msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
}
-static int TIChooseConfiguration (struct usb_device *dev)
+static int choose_config(struct usb_device *dev)
{
- // There may be multiple configurations on this device, in which case
- // we would need to read and parse all of them to find out which one
- // we want. However, we just support one config at this point,
- // configuration # 1, which is Config Descriptor 0.
+ /*
+ * There may be multiple configurations on this device, in which case
+ * we would need to read and parse all of them to find out which one
+ * we want. However, we just support one config at this point,
+ * configuration # 1, which is Config Descriptor 0.
+ */
- dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces);
- dbg ("%s - MAX Power = %d", __func__, dev->config->desc.bMaxPower*2);
+ dbg("%s - Number of Interfaces = %d",
+ __func__, dev->config->desc.bNumInterfaces);
+ dbg("%s - MAX Power = %d",
+ __func__, dev->config->desc.bMaxPower * 2);
if (dev->config->desc.bNumInterfaces != 1) {
- dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
+ dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n",
+ __func__);
return -ENODEV;
}
return 0;
}
-static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int read_rom(struct edgeport_serial *serial,
+ int start_address, int length, __u8 *buffer)
{
int status;
if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
- status = TIReadDownloadMemory (serial->serial->dev,
+ status = read_download_mem(serial->serial->dev,
start_address,
length,
serial->TI_I2C_Type,
buffer);
} else {
- status = TIReadBootMemory (serial,
- start_address,
- length,
- buffer);
+ status = read_boot_mem(serial, start_address, length,
+ buffer);
}
-
return status;
}
-static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int write_rom(struct edgeport_serial *serial, int start_address,
+ int length, __u8 *buffer)
{
if (serial->product_info.TiMode == TI_MODE_BOOT)
- return TIWriteBootMemory (serial,
- start_address,
- length,
- buffer);
+ return write_boot_mem(serial, start_address, length,
+ buffer);
if (serial->product_info.TiMode == TI_MODE_DOWNLOAD)
- return TIWriteDownloadI2C (serial,
- start_address,
- length,
- serial->TI_I2C_Type,
- buffer);
-
+ return write_i2c_mem(serial, start_address, length,
+ serial->TI_I2C_Type, buffer);
return -EINVAL;
}
/* Read a descriptor header from I2C based on type */
-static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc)
+static int get_descriptor_addr(struct edgeport_serial *serial,
+ int desc_type, struct ti_i2c_desc *rom_desc)
{
int start_address;
int status;
@@ -720,41 +688,42 @@ static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type
/* Search for requested descriptor in I2C */
start_address = 2;
do {
- status = TIReadRom (serial,
+ status = read_rom(serial,
start_address,
sizeof(struct ti_i2c_desc),
- (__u8 *)rom_desc );
+ (__u8 *)rom_desc);
if (status)
return 0;
if (rom_desc->Type == desc_type)
return start_address;
- start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
+ start_address = start_address + sizeof(struct ti_i2c_desc)
+ + rom_desc->Size;
} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
-
+
return 0;
}
/* Validate descriptor checksum */
-static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
+static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
{
__u16 i;
__u8 cs = 0;
- for (i=0; i < rom_desc->Size; i++) {
+ for (i = 0; i < rom_desc->Size; i++)
cs = (__u8)(cs + buffer[i]);
- }
+
if (cs != rom_desc->CheckSum) {
- dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
+ dbg("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
return -EINVAL;
}
return 0;
}
/* Make sure that the I2C image is good */
-static int TiValidateI2cImage (struct edgeport_serial *serial)
+static int check_i2c_image(struct edgeport_serial *serial)
{
struct device *dev = &serial->serial->dev->dev;
int status = 0;
@@ -763,120 +732,124 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
__u8 *buffer;
__u16 ttype;
- rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- dev_err (dev, "%s - out of memory\n", __func__);
+ dev_err(dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
- buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
+ buffer = kmalloc(TI_MAX_I2C_SIZE, GFP_KERNEL);
if (!buffer) {
- dev_err (dev, "%s - out of memory when allocating buffer\n", __func__);
- kfree (rom_desc);
+ dev_err(dev, "%s - out of memory when allocating buffer\n",
+ __func__);
+ kfree(rom_desc);
return -ENOMEM;
}
- // Read the first byte (Signature0) must be 0x52 or 0x10
- status = TIReadRom (serial, 0, 1, buffer);
+ /* Read the first byte (Signature0) must be 0x52 or 0x10 */
+ status = read_rom(serial, 0, 1, buffer);
if (status)
- goto ExitTiValidateI2cImage;
+ goto out;
if (*buffer != UMP5152 && *buffer != UMP3410) {
- dev_err (dev, "%s - invalid buffer signature\n", __func__);
+ dev_err(dev, "%s - invalid buffer signature\n", __func__);
status = -ENODEV;
- goto ExitTiValidateI2cImage;
+ goto out;
}
do {
- // Validate the I2C
- status = TIReadRom (serial,
+ /* Validate the I2C */
+ status = read_rom(serial,
start_address,
sizeof(struct ti_i2c_desc),
(__u8 *)rom_desc);
if (status)
break;
- if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
+ if ((start_address + sizeof(struct ti_i2c_desc) +
+ rom_desc->Size) > TI_MAX_I2C_SIZE) {
status = -ENODEV;
- dbg ("%s - structure too big, erroring out.", __func__);
+ dbg("%s - structure too big, erroring out.", __func__);
break;
}
- dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
+ dbg("%s Type = 0x%x", __func__, rom_desc->Type);
- // Skip type 2 record
+ /* Skip type 2 record */
ttype = rom_desc->Type & 0x0f;
- if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
- && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) {
- // Read the descriptor data
- status = TIReadRom(serial,
- start_address+sizeof(struct ti_i2c_desc),
- rom_desc->Size,
- buffer);
+ if (ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
+ && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO) {
+ /* Read the descriptor data */
+ status = read_rom(serial, start_address +
+ sizeof(struct ti_i2c_desc),
+ rom_desc->Size, buffer);
if (status)
break;
- status = ValidChecksum(rom_desc, buffer);
+ status = valid_csum(rom_desc, buffer);
if (status)
break;
}
- start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
+ start_address = start_address + sizeof(struct ti_i2c_desc) +
+ rom_desc->Size;
- } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE));
+ } while ((rom_desc->Type != I2C_DESC_TYPE_ION) &&
+ (start_address < TI_MAX_I2C_SIZE));
- if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE))
+ if ((rom_desc->Type != I2C_DESC_TYPE_ION) ||
+ (start_address > TI_MAX_I2C_SIZE))
status = -ENODEV;
-ExitTiValidateI2cImage:
- kfree (buffer);
- kfree (rom_desc);
+out:
+ kfree(buffer);
+ kfree(rom_desc);
return status;
}
-static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
{
int status;
int start_address;
struct ti_i2c_desc *rom_desc;
struct edge_ti_manuf_descriptor *desc;
- rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__);
+ dev_err(&serial->serial->dev->dev, "%s - out of memory\n",
+ __func__);
return -ENOMEM;
}
- start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+ start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
+ rom_desc);
if (!start_address) {
- dbg ("%s - Edge Descriptor not found in I2C", __func__);
+ dbg("%s - Edge Descriptor not found in I2C", __func__);
status = -ENODEV;
goto exit;
}
- // Read the descriptor data
- status = TIReadRom (serial,
- start_address+sizeof(struct ti_i2c_desc),
- rom_desc->Size,
- buffer);
+ /* Read the descriptor data */
+ status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
+ rom_desc->Size, buffer);
if (status)
goto exit;
-
- status = ValidChecksum(rom_desc, buffer);
-
+
+ status = valid_csum(rom_desc, buffer);
+
desc = (struct edge_ti_manuf_descriptor *)buffer;
- dbg ( "%s - IonConfig 0x%x", __func__, desc->IonConfig );
- dbg ( "%s - Version %d", __func__, desc->Version );
- dbg ( "%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev );
- dbg ( "%s - NumPorts %d", __func__, desc->NumPorts );
- dbg ( "%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts );
- dbg ( "%s - TotalPorts %d", __func__, desc->TotalPorts );
+ dbg("%s - IonConfig 0x%x", __func__, desc->IonConfig);
+ dbg("%s - Version %d", __func__, desc->Version);
+ dbg("%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev);
+ dbg("%s - NumPorts %d", __func__, desc->NumPorts);
+ dbg("%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts);
+ dbg("%s - TotalPorts %d", __func__, desc->TotalPorts);
exit:
- kfree (rom_desc);
+ kfree(rom_desc);
return status;
}
/* Build firmware header used for firmware update */
-static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
+static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
{
__u8 *buffer;
int buffer_size;
@@ -889,24 +862,28 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
const struct firmware *fw;
const char *fw_name = "edgeport/down3.bin";
- // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
- // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
- // will download the latest firmware (padded to 15.5k) into the UMP ram.
- // And finally when the device comes back up in download mode the driver will cause
- // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
- // the record type from 0xf2 to 0x02.
-
- // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record)
- buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec));
-
- buffer = kmalloc (buffer_size, GFP_KERNEL);
+ /* In order to update the I2C firmware we must change the type 2 record
+ * to type 0xF2. This will force the UMP to come up in Boot Mode.
+ * Then while in boot mode, the driver will download the latest
+ * firmware (padded to 15.5k) into the UMP ram. And finally when the
+ * device comes back up in download mode the driver will cause the new
+ * firmware to be copied from the UMP Ram to I2C and the firmware will
+ * update the record type from 0xf2 to 0x02.
+ */
+
+ /* Allocate a 15.5k buffer + 2 bytes for version number
+ * (Firmware Record) */
+ buffer_size = (((1024 * 16) - 512 ) +
+ sizeof(struct ti_i2c_firmware_rec));
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
- dev_err (dev, "%s - out of memory\n", __func__);
+ dev_err(dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
-
+
// Set entire image of 0xffs
- memset (buffer, 0xff, buffer_size);
+ memset(buffer, 0xff, buffer_size);
err = request_firmware(&fw, fw_name, dev);
if (err) {
@@ -921,16 +898,16 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
OperationalMinorVersion = fw->data[1];
OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8);
- // Copy version number into firmware record
+ /* Copy version number into firmware record */
firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
firmware_rec->Ver_Major = OperationalMajorVersion;
firmware_rec->Ver_Minor = OperationalMinorVersion;
- // Pointer to fw_down memory image
+ /* Pointer to fw_down memory image */
img_header = (struct ti_i2c_image_header *)&fw->data[4];
- memcpy (buffer + sizeof(struct ti_i2c_firmware_rec),
+ memcpy(buffer + sizeof(struct ti_i2c_firmware_rec),
&fw->data[4 + sizeof(struct ti_i2c_image_header)],
le16_to_cpu(img_header->Length));
@@ -940,12 +917,12 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
cs = (__u8)(cs + buffer[i]);
}
- kfree (buffer);
+ kfree(buffer);
- // Build new header
+ /* Build new header */
i2c_header = (struct ti_i2c_desc *)header;
firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data;
-
+
i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK;
i2c_header->Size = (__u16)buffer_size;
i2c_header->CheckSum = cs;
@@ -956,103 +933,100 @@ static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
}
/* Try to figure out what type of I2c we have */
-static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+static int i2c_type_bootmode(struct edgeport_serial *serial)
{
int status;
__u8 data;
-
- // Try to read type 2
- status = TIReadVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_READ, // Request
- DTK_ADDR_SPACE_I2C_TYPE_II, // wValue (Address type)
- 0, // wIndex
- &data, // TransferBuffer
- 0x01); // TransferBufferLength
+
+ /* Try to read type 2 */
+ status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
+ DTK_ADDR_SPACE_I2C_TYPE_II, 0, &data, 0x01);
if (status)
- dbg ("%s - read 2 status error = %d", __func__, status);
+ dbg("%s - read 2 status error = %d", __func__, status);
else
- dbg ("%s - read 2 data = 0x%x", __func__, data);
+ dbg("%s - read 2 data = 0x%x", __func__, data);
if ((!status) && (data == UMP5152 || data == UMP3410)) {
- dbg ("%s - ROM_TYPE_II", __func__);
+ dbg("%s - ROM_TYPE_II", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
return 0;
}
- // Try to read type 3
- status = TIReadVendorRequestSync (serial->serial->dev,
- UMPC_MEMORY_READ, // Request
- DTK_ADDR_SPACE_I2C_TYPE_III, // wValue (Address type)
- 0, // wIndex
- &data, // TransferBuffer
- 0x01); // TransferBufferLength
+ /* Try to read type 3 */
+ status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
+ DTK_ADDR_SPACE_I2C_TYPE_III, 0, &data, 0x01);
if (status)
- dbg ("%s - read 3 status error = %d", __func__, status);
+ dbg("%s - read 3 status error = %d", __func__, status);
else
- dbg ("%s - read 2 data = 0x%x", __func__, data);
+ dbg("%s - read 2 data = 0x%x", __func__, data);
if ((!status) && (data == UMP5152 || data == UMP3410)) {
- dbg ("%s - ROM_TYPE_III", __func__);
+ dbg("%s - ROM_TYPE_III", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
return 0;
}
- dbg ("%s - Unknown", __func__);
+ dbg("%s - Unknown", __func__);
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
return -ENODEV;
}
-static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent)
+static int bulk_xfer(struct usb_serial *serial, void *buffer,
+ int length, int *num_sent)
{
int status;
- status = usb_bulk_msg (serial->dev,
- usb_sndbulkpipe(serial->dev,
- serial->port[0]->bulk_out_endpointAddress),
- buffer,
- length,
- num_sent,
- 1000);
+ status = usb_bulk_msg(serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ serial->port[0]->bulk_out_endpointAddress),
+ buffer, length, num_sent, 1000);
return status;
}
/* Download given firmware image to the device (IN BOOT MODE) */
-static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length)
+static int download_code(struct edgeport_serial *serial, __u8 *image,
+ int image_length)
{
int status = 0;
int pos;
int transfer;
int done;
- // Transfer firmware image
+ /* Transfer firmware image */
for (pos = 0; pos < image_length; ) {
- // Read the next buffer from file
+ /* Read the next buffer from file */
transfer = image_length - pos;
if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE)
transfer = EDGE_FW_BULK_MAX_PACKET_SIZE;
- // Transfer data
- status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done);
+ /* Transfer data */
+ status = bulk_xfer(serial->serial, &image[pos],
+ transfer, &done);
if (status)
break;
- // Advance buffer pointer
+ /* Advance buffer pointer */
pos += done;
}
return status;
}
-// FIXME!!!
-static int TIConfigureBootDevice (struct usb_device *dev)
+/* FIXME!!! */
+static int config_boot_dev(struct usb_device *dev)
{
return 0;
}
+static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc)
+{
+ return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
+}
+
/**
* DownloadTIFirmware - Download run-time operating firmware to the TI5052
- *
+ *
* This routine downloads the main operating code into the TI5052, using the
* boot code already burned into E2PROM or ROM.
*/
-static int TIDownloadFirmware (struct edgeport_serial *serial)
+static int download_fw(struct edgeport_serial *serial)
{
struct device *dev = &serial->serial->dev->dev;
int status = 0;
@@ -1071,22 +1045,25 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
/* Default to type 2 i2c */
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
- status = TIChooseConfiguration (serial->serial->dev);
+ status = choose_config(serial->serial->dev);
if (status)
return status;
interface = &serial->serial->interface->cur_altsetting->desc;
if (!interface) {
- dev_err (dev, "%s - no interface set, error!\n", __func__);
+ dev_err(dev, "%s - no interface set, error!\n", __func__);
return -ENODEV;
}
- // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
- // if we have more than one endpoint we are definitely in download mode
+ /*
+ * Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
+ * if we have more than one endpoint we are definitely in download
+ * mode
+ */
if (interface->bNumEndpoints > 1)
serial->product_info.TiMode = TI_MODE_DOWNLOAD;
else
- // Otherwise we will remain in configuring mode
+ /* Otherwise we will remain in configuring mode */
serial->product_info.TiMode = TI_MODE_CONFIGURING;
/********************************************************************/
@@ -1097,256 +1074,273 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
- status = TiValidateI2cImage (serial);
+ status = check_i2c_image(serial);
if (status) {
dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
return status;
}
-
+
/* Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport
*/
- ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
if (!ti_manuf_desc) {
- dev_err (dev, "%s - out of memory.\n", __func__);
+ dev_err(dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
- status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+ status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
if (status) {
- kfree (ti_manuf_desc);
+ kfree(ti_manuf_desc);
return status;
}
- // Check version number of ION descriptor
- if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
- dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__,
- TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
- kfree (ti_manuf_desc);
- return -EINVAL;
- }
+ /* Check version number of ION descriptor */
+ if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+ dbg("%s - Wrong CPU Rev %d (Must be 2)",
+ __func__, ti_cpu_rev(ti_manuf_desc));
+ kfree(ti_manuf_desc);
+ return -EINVAL;
+ }
- rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+ rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- dev_err (dev, "%s - out of memory.\n", __func__);
- kfree (ti_manuf_desc);
+ dev_err(dev, "%s - out of memory.\n", __func__);
+ kfree(ti_manuf_desc);
return -ENOMEM;
}
- // Search for type 2 record (firmware record)
- if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) {
+ /* Search for type 2 record (firmware record) */
+ start_address = get_descriptor_addr(serial,
+ I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
+ if (start_address != 0) {
struct ti_i2c_firmware_rec *firmware_version;
__u8 record;
- dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
+ dbg("%s - Found Type FIRMWARE (Type 2) record",
+ __func__);
- firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
+ firmware_version = kmalloc(sizeof(*firmware_version),
+ GFP_KERNEL);
if (!firmware_version) {
- dev_err (dev, "%s - out of memory.\n", __func__);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dev_err(dev, "%s - out of memory.\n", __func__);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENOMEM;
}
- // Validate version number
- // Read the descriptor data
- status = TIReadRom (serial,
- start_address+sizeof(struct ti_i2c_desc),
+ /* Validate version number
+ * Read the descriptor data
+ */
+ status = read_rom(serial, start_address +
+ sizeof(struct ti_i2c_desc),
sizeof(struct ti_i2c_firmware_rec),
(__u8 *)firmware_version);
if (status) {
- kfree (firmware_version);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
- // Check version number of download with current version in I2c
- download_cur_ver = (firmware_version->Ver_Major << 8) +
+ /* Check version number of download with current
+ version in I2c */
+ download_cur_ver = (firmware_version->Ver_Major << 8) +
(firmware_version->Ver_Minor);
download_new_ver = (OperationalMajorVersion << 8) +
(OperationalMinorVersion);
- dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d",
- __func__,
- firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
+ dbg("%s - >> FW Versions Device %d.%d Driver %d.%d",
+ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalMajorVersion,
+ OperationalMinorVersion);
- // Check if we have an old version in the I2C and update if necessary
+ /* Check if we have an old version in the I2C and
+ update if necessary */
if (download_cur_ver != download_new_ver) {
- dbg ("%s - Update I2C Download from %d.%d to %d.%d",
- __func__,
- firmware_version->Ver_Major,
- firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
-
- // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
- // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
- // will download the latest firmware (padded to 15.5k) into the UMP ram.
- // And finally when the device comes back up in download mode the driver will cause
- // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
- // the record type from 0xf2 to 0x02.
-
+ dbg("%s - Update I2C dld from %d.%d to %d.%d",
+ __func__,
+ firmware_version->Ver_Major,
+ firmware_version->Ver_Minor,
+ OperationalMajorVersion,
+ OperationalMinorVersion);
+
+ /* In order to update the I2C firmware we must
+ * change the type 2 record to type 0xF2. This
+ * will force the UMP to come up in Boot Mode.
+ * Then while in boot mode, the driver will
+ * download the latest firmware (padded to
+ * 15.5k) into the UMP ram. Finally when the
+ * device comes back up in download mode the
+ * driver will cause the new firmware to be
+ * copied from the UMP Ram to I2C and the
+ * firmware will update the record type from
+ * 0xf2 to 0x02.
+ */
record = I2C_DESC_TYPE_FIRMWARE_BLANK;
- // Change the I2C Firmware record type to 0xf2 to trigger an update
- status = TIWriteRom (serial,
- start_address,
- sizeof(record),
- &record);
+ /* Change the I2C Firmware record type to
+ 0xf2 to trigger an update */
+ status = write_rom(serial, start_address,
+ sizeof(record), &record);
if (status) {
- kfree (firmware_version);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
- // verify the write -- must do this in order for write to
- // complete before we do the hardware reset
- status = TIReadRom (serial,
+ /* verify the write -- must do this in order
+ * for write to complete before we do the
+ * hardware reset
+ */
+ status = read_rom(serial,
start_address,
sizeof(record),
&record);
-
if (status) {
- kfree (firmware_version);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
- dev_err (dev, "%s - error resetting device\n", __func__);
- kfree (firmware_version);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dev_err(dev,
+ "%s - error resetting device\n",
+ __func__);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENODEV;
}
- dbg ("%s - HARDWARE RESET", __func__);
+ dbg("%s - HARDWARE RESET", __func__);
- // Reset UMP -- Back to BOOT MODE
- status = TISendVendorRequestSync (serial->serial->dev,
- UMPC_HARDWARE_RESET, // Request
- 0, // wValue
- 0, // wIndex
- NULL, // TransferBuffer
- 0); // TransferBufferLength
+ /* Reset UMP -- Back to BOOT MODE */
+ status = ti_vsend_sync(serial->serial->dev,
+ UMPC_HARDWARE_RESET,
+ 0, 0, NULL, 0);
- dbg ( "%s - HARDWARE RESET return %d", __func__, status);
+ dbg("%s - HARDWARE RESET return %d",
+ __func__, status);
/* return an error on purpose. */
- kfree (firmware_version);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(firmware_version);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENODEV;
}
- kfree (firmware_version);
+ kfree(firmware_version);
}
- // Search for type 0xF2 record (firmware blank record)
- else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
- #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec))
+ /* Search for type 0xF2 record (firmware blank record) */
+ else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \
+ sizeof(struct ti_i2c_firmware_rec))
__u8 *header;
__u8 *vheader;
- header = kmalloc (HEADER_SIZE, GFP_KERNEL);
+ header = kmalloc(HEADER_SIZE, GFP_KERNEL);
if (!header) {
- dev_err (dev, "%s - out of memory.\n", __func__);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dev_err(dev, "%s - out of memory.\n", __func__);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENOMEM;
}
-
- vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
+
+ vheader = kmalloc(HEADER_SIZE, GFP_KERNEL);
if (!vheader) {
- dev_err (dev, "%s - out of memory.\n", __func__);
- kfree (header);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dev_err(dev, "%s - out of memory.\n", __func__);
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return -ENOMEM;
}
-
- dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__);
-
- // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
- // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
- // will download the latest firmware (padded to 15.5k) into the UMP ram.
- // And finally when the device comes back up in download mode the driver will cause
- // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
- // the record type from 0xf2 to 0x02.
- status = BuildI2CFirmwareHeader(header, dev);
+
+ dbg("%s - Found Type BLANK FIRMWARE (Type F2) record",
+ __func__);
+
+ /*
+ * In order to update the I2C firmware we must change
+ * the type 2 record to type 0xF2. This will force the
+ * UMP to come up in Boot Mode. Then while in boot
+ * mode, the driver will download the latest firmware
+ * (padded to 15.5k) into the UMP ram. Finally when the
+ * device comes back up in download mode the driver
+ * will cause the new firmware to be copied from the
+ * UMP Ram to I2C and the firmware will update the
+ * record type from 0xf2 to 0x02.
+ */
+ status = build_i2c_fw_hdr(header, dev);
if (status) {
- kfree (vheader);
- kfree (header);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(vheader);
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
- // Update I2C with type 0xf2 record with correct size and checksum
- status = TIWriteRom (serial,
+ /* Update I2C with type 0xf2 record with correct
+ size and checksum */
+ status = write_rom(serial,
start_address,
HEADER_SIZE,
header);
if (status) {
- kfree (vheader);
- kfree (header);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(vheader);
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
- // verify the write -- must do this in order for write to
- // complete before we do the hardware reset
- status = TIReadRom (serial,
- start_address,
- HEADER_SIZE,
- vheader);
+ /* verify the write -- must do this in order for
+ write to complete before we do the hardware reset */
+ status = read_rom(serial, start_address,
+ HEADER_SIZE, vheader);
if (status) {
- dbg ("%s - can't read header back", __func__);
- kfree (vheader);
- kfree (header);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dbg("%s - can't read header back", __func__);
+ kfree(vheader);
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
if (memcmp(vheader, header, HEADER_SIZE)) {
- dbg ("%s - write download record failed", __func__);
- kfree (vheader);
- kfree (header);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dbg("%s - write download record failed",
+ __func__);
+ kfree(vheader);
+ kfree(header);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
- kfree (vheader);
- kfree (header);
+ kfree(vheader);
+ kfree(header);
- dbg ("%s - Start firmware update", __func__);
+ dbg("%s - Start firmware update", __func__);
- // Tell firmware to copy download image into I2C
- status = TISendVendorRequestSync (serial->serial->dev,
- UMPC_COPY_DNLD_TO_I2C, // Request
- 0, // wValue
- 0, // wIndex
- NULL, // TransferBuffer
- 0); // TransferBufferLength
+ /* Tell firmware to copy download image into I2C */
+ status = ti_vsend_sync(serial->serial->dev,
+ UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0);
- dbg ("%s - Update complete 0x%x", __func__, status);
+ dbg("%s - Update complete 0x%x", __func__, status);
if (status) {
- dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ dev_err(dev,
+ "%s - UMPC_COPY_DNLD_TO_I2C failed\n",
+ __func__);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return status;
}
}
// The device is running the download code
- kfree (rom_desc);
- kfree (ti_manuf_desc);
+ kfree(rom_desc);
+ kfree(ti_manuf_desc);
return 0;
}
@@ -1355,32 +1349,26 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
/********************************************************************/
dbg("%s - RUNNING IN BOOT MODE", __func__);
- // Configure the TI device so we can use the BULK pipes for download
- status = TIConfigureBootDevice (serial->serial->dev);
+ /* Configure the TI device so we can use the BULK pipes for download */
+ status = config_boot_dev(serial->serial->dev);
if (status)
return status;
- if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
- dbg ("%s - VID = 0x%x", __func__,
+ if (le16_to_cpu(serial->serial->dev->descriptor.idVendor)
+ != USB_VENDOR_ID_ION) {
+ dbg("%s - VID = 0x%x", __func__,
le16_to_cpu(serial->serial->dev->descriptor.idVendor));
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
- goto StayInBootMode;
+ goto stayinbootmode;
}
- // We have an ION device (I2c Must be programmed)
- // Determine I2C image type
- if (TIGetI2cTypeInBootMode(serial)) {
- goto StayInBootMode;
- }
+ /* We have an ION device (I2c Must be programmed)
+ Determine I2C image type */
+ if (i2c_type_bootmode(serial))
+ goto stayinbootmode;
- // Registry variable set?
- if (TIStayInBootMode) {
- dbg ("%s - TIStayInBootMode", __func__);
- goto StayInBootMode;
- }
-
- // Check for ION Vendor ID and that the I2C is valid
- if (!TiValidateI2cImage(serial)) {
+ /* Check for ION Vendor ID and that the I2C is valid */
+ if (!check_i2c_image(serial)) {
struct ti_i2c_image_header *header;
int i;
__u8 cs = 0;
@@ -1393,49 +1381,52 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
/* Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport
*/
- ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+ ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
if (!ti_manuf_desc) {
- dev_err (dev, "%s - out of memory.\n", __func__);
+ dev_err(dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
- status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+ status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
if (status) {
- kfree (ti_manuf_desc);
- goto StayInBootMode;
+ kfree(ti_manuf_desc);
+ goto stayinbootmode;
}
- // Check for version 2
- if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
- dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__,
- TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
- kfree (ti_manuf_desc);
- goto StayInBootMode;
+ /* Check for version 2 */
+ if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+ dbg("%s - Wrong CPU Rev %d (Must be 2)",
+ __func__, ti_cpu_rev(ti_manuf_desc));
+ kfree(ti_manuf_desc);
+ goto stayinbootmode;
}
- kfree (ti_manuf_desc);
+ kfree(ti_manuf_desc);
- // In order to update the I2C firmware we must change the type 2 record to type 0xF2.
- // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver
- // will download the latest firmware (padded to 15.5k) into the UMP ram.
- // And finally when the device comes back up in download mode the driver will cause
- // the new firmware to be copied from the UMP Ram to I2C and the firmware will update
- // the record type from 0xf2 to 0x02.
-
/*
+ * In order to update the I2C firmware we must change the type
+ * 2 record to type 0xF2. This will force the UMP to come up
+ * in Boot Mode. Then while in boot mode, the driver will
+ * download the latest firmware (padded to 15.5k) into the
+ * UMP ram. Finally when the device comes back up in download
+ * mode the driver will cause the new firmware to be copied
+ * from the UMP Ram to I2C and the firmware will update the
+ * record type from 0xf2 to 0x02.
+ *
* Do we really have to copy the whole firmware image,
* or could we do this in place!
*/
- // Allocate a 15.5k buffer + 3 byte header
- buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
- buffer = kmalloc (buffer_size, GFP_KERNEL);
+ /* Allocate a 15.5k buffer + 3 byte header */
+ buffer_size = (((1024 * 16) - 512) +
+ sizeof(struct ti_i2c_image_header));
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
- dev_err (dev, "%s - out of memory\n", __func__);
+ dev_err(dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
-
- // Initialize the buffer to 0xff (pad the buffer)
- memset (buffer, 0xff, buffer_size);
+
+ /* Initialize the buffer to 0xff (pad the buffer) */
+ memset(buffer, 0xff, buffer_size);
err = request_firmware(&fw, fw_name, dev);
if (err) {
@@ -1447,38 +1438,43 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
memcpy(buffer, &fw->data[4], fw->size - 4);
release_firmware(fw);
- for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) {
+ for (i = sizeof(struct ti_i2c_image_header);
+ i < buffer_size; i++) {
cs = (__u8)(cs + buffer[i]);
}
-
+
header = (struct ti_i2c_image_header *)buffer;
-
- // update length and checksum after padding
- header->Length = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header)));
+
+ /* update length and checksum after padding */
+ header->Length = cpu_to_le16((__u16)(buffer_size -
+ sizeof(struct ti_i2c_image_header)));
header->CheckSum = cs;
- // Download the operational code
- dbg ("%s - Downloading operational code image (TI UMP)", __func__);
- status = TIDownloadCodeImage (serial, buffer, buffer_size);
+ /* Download the operational code */
+ dbg("%s - Downloading operational code image (TI UMP)",
+ __func__);
+ status = download_code(serial, buffer, buffer_size);
- kfree (buffer);
+ kfree(buffer);
if (status) {
- dbg ("%s - Error downloading operational code image", __func__);
+ dbg("%s - Error downloading operational code image",
+ __func__);
return status;
}
- // Device will reboot
+ /* Device will reboot */
serial->product_info.TiMode = TI_MODE_TRANSITIONING;
- dbg ("%s - Download successful -- Device rebooting...", __func__);
+ dbg("%s - Download successful -- Device rebooting...",
+ __func__);
/* return an error on purpose */
return -ENODEV;
}
-StayInBootMode:
- // Eprom is invalid or blank stay in boot mode
+stayinbootmode:
+ /* Eprom is invalid or blank stay in boot mode */
dbg("%s - STAYING IN BOOT MODE", __func__);
serial->product_info.TiMode = TI_MODE_BOOT;
@@ -1486,156 +1482,33 @@ StayInBootMode:
}
-static int TISetDtr (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
- port->shadow_mcr |= MCR_DTR;
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_DTR,
- (__u8)(UMPM_UART1_PORT + port_number),
- 1, /* set */
- NULL,
- 0);
-}
-
-static int TIClearDtr (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
- port->shadow_mcr &= ~MCR_DTR;
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_DTR,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0, /* clear */
- NULL,
- 0);
-}
-
-static int TISetRts (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
- port->shadow_mcr |= MCR_RTS;
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_RTS,
- (__u8)(UMPM_UART1_PORT + port_number),
- 1, /* set */
- NULL,
- 0);
-}
-
-static int TIClearRts (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
- port->shadow_mcr &= ~MCR_RTS;
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_RTS,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0, /* clear */
- NULL,
- 0);
-}
-
-static int TISetLoopBack (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_LOOPBACK,
- (__u8)(UMPM_UART1_PORT + port_number),
- 1, /* set */
- NULL,
- 0);
-}
-
-static int TIClearLoopBack (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_LOOPBACK,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0, /* clear */
- NULL,
- 0);
-}
-
-static int TISetBreak (struct edgeport_port *port)
+static int ti_do_config(struct edgeport_port *port, int feature, int on)
{
int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
-
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_BREAK,
- (__u8)(UMPM_UART1_PORT + port_number),
- 1, /* set */
- NULL,
- 0);
+ on = !!on; /* 1 or 0 not bitmask */
+ return send_cmd(port->port->serial->dev,
+ feature, (__u8)(UMPM_UART1_PORT + port_number),
+ on, NULL, 0);
}
-static int TIClearBreak (struct edgeport_port *port)
-{
- int port_number = port->port->number - port->port->serial->minor;
-
- dbg ("%s", __func__);
- return TIWriteCommandSync (port->port->serial->dev,
- UMPC_SET_CLR_BREAK,
- (__u8)(UMPM_UART1_PORT + port_number),
- 0, /* clear */
- NULL,
- 0);
-}
-
-static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
+static int restore_mcr(struct edgeport_port *port, __u8 mcr)
{
int status = 0;
- dbg ("%s - %x", __func__, mcr);
-
- if (mcr & MCR_DTR)
- status = TISetDtr (port);
- else
- status = TIClearDtr (port);
+ dbg("%s - %x", __func__, mcr);
+ status = ti_do_config(port, UMPC_SET_CLR_DTR, mcr & MCR_DTR);
if (status)
return status;
-
- if (mcr & MCR_RTS)
- status = TISetRts (port);
- else
- status = TIClearRts (port);
-
+ status = ti_do_config(port, UMPC_SET_CLR_RTS, mcr & MCR_RTS);
if (status)
return status;
-
- if (mcr & MCR_LOOPBACK)
- status = TISetLoopBack (port);
- else
- status = TIClearLoopBack (port);
-
- return status;
+ return ti_do_config(port, UMPC_SET_CLR_LOOPBACK, mcr & MCR_LOOPBACK);
}
-
-
/* Convert TI LSR to standard UART flags */
-static __u8 MapLineStatus (__u8 ti_lsr)
+static __u8 map_line_status(__u8 ti_lsr)
{
__u8 lsr = 0;
@@ -1647,22 +1520,23 @@ static __u8 MapLineStatus (__u8 ti_lsr)
MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */
MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */
MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */
- MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */
- MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */
+ MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* rx data available */
+ MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* tx hold reg empty */
#undef MAP_FLAG
return lsr;
}
-static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
{
struct async_icount *icount;
struct tty_struct *tty;
- dbg ("%s - %02x", __func__, msr);
+ dbg("%s - %02x", __func__, msr);
- if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+ if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
+ EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
icount = &edge_port->icount;
/* update input line counters */
@@ -1674,13 +1548,13 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
icount->dcd++;
if (msr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible (&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->delta_msr_wait);
}
/* Save the new modem status */
edge_port->shadow_msr = msr & 0xf0;
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
/* handle CTS flow control */
if (tty && C_CRTSCTS(tty)) {
if (msr & EDGEPORT_MSR_CTS) {
@@ -1694,26 +1568,27 @@ static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
return;
}
-static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data)
+static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
+ __u8 lsr, __u8 data)
{
struct async_icount *icount;
- __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+ __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
+ LSR_FRM_ERR | LSR_BREAK));
- dbg ("%s - %02x", __func__, new_lsr);
+ dbg("%s - %02x", __func__, new_lsr);
edge_port->shadow_lsr = lsr;
- if (new_lsr & LSR_BREAK) {
+ if (new_lsr & LSR_BREAK)
/*
* Parity and Framing errors only count if they
* occur exclusive of a break being received.
*/
new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
- }
/* Place LSR data byte into Rx buffer */
- if (lsr_data && edge_port->port->tty)
- edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
+ if (lsr_data && edge_port->port->port.tty)
+ edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
/* update input line counters */
icount = &edge_port->icount;
@@ -1728,7 +1603,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
}
-static void edge_interrupt_callback (struct urb *urb)
+static void edge_interrupt_callback(struct urb *urb)
{
struct edgeport_serial *edge_serial = urb->context;
struct usb_serial_port *port;
@@ -1762,66 +1637,71 @@ static void edge_interrupt_callback (struct urb *urb)
}
if (!length) {
- dbg ("%s - no data in urb", __func__);
+ dbg("%s - no data in urb", __func__);
goto exit;
}
-
- usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
-
+
+ usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+ __func__, length, data);
+
if (length != 2) {
- dbg ("%s - expecting packet of size 2, got %d", __func__, length);
+ dbg("%s - expecting packet of size 2, got %d",
+ __func__, length);
goto exit;
}
- port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
- function = TIUMP_GET_FUNC_FROM_CODE (data[0]);
- dbg ("%s - port_number %d, function %d, info 0x%x",
+ port_number = TIUMP_GET_PORT_FROM_CODE(data[0]);
+ function = TIUMP_GET_FUNC_FROM_CODE(data[0]);
+ dbg("%s - port_number %d, function %d, info 0x%x",
__func__, port_number, function, data[1]);
port = edge_serial->serial->port[port_number];
edge_port = usb_get_serial_port_data(port);
if (!edge_port) {
- dbg ("%s - edge_port not found", __func__);
+ dbg("%s - edge_port not found", __func__);
return;
}
switch (function) {
case TIUMP_INTERRUPT_CODE_LSR:
- lsr = MapLineStatus(data[1]);
+ lsr = map_line_status(data[1]);
if (lsr & UMP_UART_LSR_DATA_MASK) {
- /* Save the LSR event for bulk read completion routine */
- dbg ("%s - LSR Event Port %u LSR Status = %02x",
+ /* Save the LSR event for bulk read
+ completion routine */
+ dbg("%s - LSR Event Port %u LSR Status = %02x",
__func__, port_number, lsr);
edge_port->lsr_event = 1;
edge_port->lsr_mask = lsr;
} else {
- dbg ("%s - ===== Port %d LSR Status = %02x ======",
+ dbg("%s - ===== Port %d LSR Status = %02x ======",
__func__, port_number, lsr);
- handle_new_lsr (edge_port, 0, lsr, 0);
+ handle_new_lsr(edge_port, 0, lsr, 0);
}
break;
- case TIUMP_INTERRUPT_CODE_MSR: // MSR
+ case TIUMP_INTERRUPT_CODE_MSR: /* MSR */
/* Copy MSR from UMP */
msr = data[1];
- dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
+ dbg("%s - ===== Port %u MSR Status = %02x ======\n",
__func__, port_number, msr);
- handle_new_msr (edge_port, msr);
+ handle_new_msr(edge_port, msr);
break;
default:
- dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
- __func__, data[1]);
+ dev_err(&urb->dev->dev,
+ "%s - Unknown Interrupt code from UMP %x\n",
+ __func__, data[1]);
break;
-
+
}
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
__func__, retval);
}
-static void edge_bulk_in_callback (struct urb *urb)
+static void edge_bulk_in_callback(struct urb *urb)
{
struct edgeport_port *edge_port = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -1844,15 +1724,16 @@ static void edge_bulk_in_callback (struct urb *urb)
__func__, status);
return;
default:
- dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
- __func__, status);
+ dev_err(&urb->dev->dev,
+ "%s - nonzero read bulk status received: %d\n",
+ __func__, status);
}
if (status == -EPIPE)
goto exit;
if (status) {
- dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
+ dev_err(&urb->dev->dev, "%s - stopping read!\n", __func__);
return;
}
@@ -1860,23 +1741,24 @@ static void edge_bulk_in_callback (struct urb *urb)
if (edge_port->lsr_event) {
edge_port->lsr_event = 0;
- dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
+ dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
__func__, port_number, edge_port->lsr_mask, *data);
- handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
+ handle_new_lsr(edge_port, 1, edge_port->lsr_mask, *data);
/* Adjust buffer length/pointer */
--urb->actual_length;
++data;
}
- tty = edge_port->port->tty;
+ tty = edge_port->port->port.tty;
if (tty && urb->actual_length) {
- usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data);
-
- if (edge_port->close_pending) {
- dbg ("%s - close is pending, dropping data on the floor.", __func__);
- } else {
- edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
- }
+ usb_serial_debug_data(debug, &edge_port->port->dev,
+ __func__, urb->actual_length, data);
+ if (edge_port->close_pending)
+ dbg("%s - close pending, dropping data on the floor",
+ __func__);
+ else
+ edge_tty_recv(&edge_port->port->dev, tty, data,
+ urb->actual_length);
edge_port->icount.rx += urb->actual_length;
}
@@ -1891,37 +1773,31 @@ exit:
}
spin_unlock(&edge_port->ep_lock);
if (retval)
- dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
__func__, retval);
}
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length)
{
- int cnt;
-
- do {
- cnt = tty_buffer_request_room(tty, length);
- if (cnt < length) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
- __func__, length - cnt);
- if(cnt == 0)
- break;
- }
- tty_insert_flip_string(tty, data, cnt);
- data += cnt;
- length -= cnt;
- } while (length > 0);
+ int queued;
+ tty_buffer_request_room(tty, length);
+ queued = tty_insert_flip_string(tty, data, length);
+ if (queued < length)
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __func__, length - queued);
tty_flip_buffer_push(tty);
}
-static void edge_bulk_out_callback (struct urb *urb)
+static void edge_bulk_out_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status = urb->status;
- dbg ("%s - port %d", __func__, port->number);
+ dbg("%s - port %d", __func__, port->number);
edge_port->ep_write_urb_in_use = 0;
@@ -1942,10 +1818,11 @@ static void edge_bulk_out_callback (struct urb *urb)
}
/* send any buffered data */
- edge_send(port);
+ edge_send(port->port.tty);
}
-static int edge_open (struct usb_serial_port *port, struct file * filp)
+static int edge_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial;
@@ -1961,122 +1838,125 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
if (edge_port == NULL)
return -ENODEV;
- port->tty->low_latency = low_latency;
+ if (tty)
+ tty->low_latency = low_latency;
port_number = port->number - port->serial->minor;
switch (port_number) {
- case 0:
- edge_port->uart_base = UMPMEM_BASE_UART1;
- edge_port->dma_address = UMPD_OEDB1_ADDRESS;
- break;
- case 1:
- edge_port->uart_base = UMPMEM_BASE_UART2;
- edge_port->dma_address = UMPD_OEDB2_ADDRESS;
- break;
- default:
- dev_err (&port->dev, "Unknown port number!!!\n");
- return -ENODEV;
+ case 0:
+ edge_port->uart_base = UMPMEM_BASE_UART1;
+ edge_port->dma_address = UMPD_OEDB1_ADDRESS;
+ break;
+ case 1:
+ edge_port->uart_base = UMPMEM_BASE_UART2;
+ edge_port->dma_address = UMPD_OEDB2_ADDRESS;
+ break;
+ default:
+ dev_err(&port->dev, "Unknown port number!!!\n");
+ return -ENODEV;
}
- dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
- __func__, port_number, edge_port->uart_base, edge_port->dma_address);
+ dbg("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
+ __func__, port_number, edge_port->uart_base,
+ edge_port->dma_address);
dev = port->serial->dev;
- memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
- init_waitqueue_head (&edge_port->delta_msr_wait);
+ memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+ init_waitqueue_head(&edge_port->delta_msr_wait);
/* turn off loopback */
- status = TIClearLoopBack (edge_port);
+ status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
if (status) {
- dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
+ dev_err(&port->dev,
+ "%s - cannot send clear loopback command, %d\n",
__func__, status);
return status;
}
-
+
/* set up the port settings */
- edge_set_termios (port, port->tty->termios);
+ if (tty)
+ edge_set_termios(tty, port, port->port.tty->termios);
/* open up the port */
/* milliseconds to timeout for DMA transfer */
transaction_timeout = 2;
- edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) );
+ edge_port->ump_read_timeout =
+ max(20, ((transaction_timeout * 3) / 2));
- // milliseconds to timeout for DMA transfer
- open_settings = (u8)(UMP_DMA_MODE_CONTINOUS |
- UMP_PIPE_TRANS_TIMEOUT_ENA |
+ /* milliseconds to timeout for DMA transfer */
+ open_settings = (u8)(UMP_DMA_MODE_CONTINOUS |
+ UMP_PIPE_TRANS_TIMEOUT_ENA |
(transaction_timeout << 2));
- dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
+ dbg("%s - Sending UMPC_OPEN_PORT", __func__);
/* Tell TI to open and start the port */
- status = TIWriteCommandSync (dev,
- UMPC_OPEN_PORT,
- (u8)(UMPM_UART1_PORT + port_number),
- open_settings,
- NULL,
- 0);
+ status = send_cmd(dev, UMPC_OPEN_PORT,
+ (u8)(UMPM_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
- dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send open command, %d\n",
+ __func__, status);
return status;
}
/* Start the DMA? */
- status = TIWriteCommandSync (dev,
- UMPC_START_PORT,
- (u8)(UMPM_UART1_PORT + port_number),
- 0,
- NULL,
- 0);
+ status = send_cmd(dev, UMPC_START_PORT,
+ (u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
- dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send start DMA command, %d\n",
+ __func__, status);
return status;
}
/* Clear TX and RX buffers in UMP */
- status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
+ status = purge_port(port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
if (status) {
- dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - cannot send clear buffers command, %d\n",
+ __func__, status);
return status;
}
/* Read Initial MSR */
- status = TIReadVendorRequestSync (dev,
- UMPC_READ_MSR, // Request
- 0, // wValue
- (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address)
- &edge_port->shadow_msr, // TransferBuffer
- 1); // TransferBufferLength
+ status = ti_vread_sync(dev, UMPC_READ_MSR, 0,
+ (__u16)(UMPM_UART1_PORT + port_number),
+ &edge_port->shadow_msr, 1);
if (status) {
- dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send read MSR command, %d\n",
+ __func__, status);
return status;
}
- dbg ("ShadowMSR 0x%X", edge_port->shadow_msr);
-
+ dbg("ShadowMSR 0x%X", edge_port->shadow_msr);
+
/* Set Initial MCR */
edge_port->shadow_mcr = MCR_RTS | MCR_DTR;
- dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr);
+ dbg("ShadowMCR 0x%X", edge_port->shadow_mcr);
edge_serial = edge_port->edge_serial;
if (mutex_lock_interruptible(&edge_serial->es_lock))
return -ERESTARTSYS;
if (edge_serial->num_ports_open == 0) {
- /* we are the first port to be opened, let's post the interrupt urb */
+ /* we are the first port to open, post the interrupt urb */
urb = edge_serial->serial->port[0]->interrupt_in_urb;
if (!urb) {
- dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__);
+ dev_err(&port->dev,
+ "%s - no interrupt urb present, exiting\n",
+ __func__);
status = -EINVAL;
goto release_es_lock;
}
urb->complete = edge_interrupt_callback;
urb->context = edge_serial;
urb->dev = dev;
- status = usb_submit_urb (urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - usb_submit_urb failed with value %d\n",
+ __func__, status);
goto release_es_lock;
}
}
@@ -2085,13 +1965,14 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
* reset the data toggle on the bulk endpoints to work around bug in
* host controllers where things get out of sync some times
*/
- usb_clear_halt (dev, port->write_urb->pipe);
- usb_clear_halt (dev, port->read_urb->pipe);
+ usb_clear_halt(dev, port->write_urb->pipe);
+ usb_clear_halt(dev, port->read_urb->pipe);
/* start up our bulk read urb */
urb = port->read_urb;
if (!urb) {
- dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__);
+ dev_err(&port->dev, "%s - no read urb present, exiting\n",
+ __func__);
status = -EINVAL;
goto unlink_int_urb;
}
@@ -2099,9 +1980,11 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
urb->complete = edge_bulk_in_callback;
urb->context = edge_port;
urb->dev = dev;
- status = usb_submit_urb (urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - read bulk usb_submit_urb failed with value %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -2119,7 +2002,8 @@ release_es_lock:
return status;
}
-static void edge_close (struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -2127,18 +2011,18 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
int status;
dbg("%s - port %d", __func__, port->number);
-
+
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
- if ((edge_serial == NULL) || (edge_port == NULL))
+ if (edge_serial == NULL || edge_port == NULL)
return;
-
- /* The bulkreadcompletion routine will check
+
+ /* The bulkreadcompletion routine will check
* this flag and dump add read data */
edge_port->close_pending = 1;
/* chase the port close and flush */
- TIChasePort (edge_port, (HZ*closing_wait)/100, 1);
+ chase_port(edge_port, (HZ * closing_wait) / 100, 1);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->write_urb);
@@ -2148,7 +2032,7 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
* send a close port command to it */
dbg("%s - send umpc_close_port", __func__);
port_number = port->number - port->serial->minor;
- status = TIWriteCommandSync (port->serial->dev,
+ status = send_cmd(port->serial->dev,
UMPC_CLOSE_PORT,
(__u8)(UMPM_UART1_PORT + port_number),
0,
@@ -2167,7 +2051,8 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
dbg("%s - exited", __func__);
}
-static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned long flags;
@@ -2188,16 +2073,16 @@ static int edge_write (struct usb_serial_port *port, const unsigned char *data,
count = edge_buf_put(edge_port->ep_out_buf, data, count);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- edge_send(port);
+ edge_send(tty);
return count;
}
-static void edge_send(struct usb_serial_port *port)
+static void edge_send(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int count, result;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned long flags;
@@ -2223,11 +2108,12 @@ static void edge_send(struct usb_serial_port *port)
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
/* set up our urb */
- usb_fill_bulk_urb (port->write_urb, port->serial->dev,
- usb_sndbulkpipe (port->serial->dev,
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
edge_bulk_out_callback,
@@ -2236,23 +2122,23 @@ static void edge_send(struct usb_serial_port *port)
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
edge_port->ep_write_urb_in_use = 0;
- // TODO: reschedule edge_send
- } else {
+ /* TODO: reschedule edge_send */
+ } else
edge_port->icount.tx += count;
- }
/* wakeup any process waiting for writes to complete */
/* there is now more room in the buffer for new writes */
- if (tty) {
- /* let the tty driver wakeup if it has a special write_wakeup function */
+ if (tty)
tty_wakeup(tty);
- }
}
-static int edge_write_room (struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -2260,9 +2146,9 @@ static int edge_write_room (struct usb_serial_port *port)
dbg("%s - port %d", __func__, port->number);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->close_pending == 1)
- return -ENODEV;
+ return 0;
spin_lock_irqsave(&edge_port->ep_lock, flags);
room = edge_buf_space_avail(edge_port->ep_out_buf);
@@ -2272,8 +2158,9 @@ static int edge_write_room (struct usb_serial_port *port)
return room;
}
-static int edge_chars_in_buffer (struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -2281,22 +2168,22 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
dbg("%s - port %d", __func__, port->number);
if (edge_port == NULL)
- return -ENODEV;
+ return 0;
if (edge_port->close_pending == 1)
- return -ENODEV;
+ return 0;
spin_lock_irqsave(&edge_port->ep_lock, flags);
chars = edge_buf_data_avail(edge_port->ep_out_buf);
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- dbg ("%s - returns %d", __func__, chars);
+ dbg("%s - returns %d", __func__, chars);
return chars;
}
-static void edge_throttle (struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -2304,16 +2191,10 @@ static void edge_throttle (struct usb_serial_port *port)
if (edge_port == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = edge_write (port, &stop_char, 1);
+ status = edge_write(tty, port, &stop_char, 1);
if (status <= 0) {
dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
}
@@ -2326,10 +2207,10 @@ static void edge_throttle (struct usb_serial_port *port)
}
-static void edge_unthrottle (struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -2337,27 +2218,22 @@ static void edge_unthrottle (struct usb_serial_port *port)
if (edge_port == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg ("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = edge_write (port, &start_char, 1);
+ status = edge_write(tty, port, &start_char, 1);
if (status <= 0) {
dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
}
}
-
/* if we are implementing RTS/CTS, restart reads */
/* are the Edgeport will assert the RTS line */
if (C_CRTSCTS(tty)) {
status = restart_read(edge_port);
if (status)
- dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - read bulk usb_submit_urb failed: %d\n",
+ __func__, status);
}
}
@@ -2398,22 +2274,23 @@ static int restart_read(struct edgeport_port *edge_port)
return status;
}
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
+static void change_port_settings(struct tty_struct *tty,
+ struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct ump_uart_config *config;
- struct tty_struct *tty;
int baud;
unsigned cflag;
int status;
- int port_number = edge_port->port->number - edge_port->port->serial->minor;
+ int port_number = edge_port->port->number -
+ edge_port->port->serial->minor;
dbg("%s - port %d", __func__, edge_port->port->number);
- tty = edge_port->port->tty;
-
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
- dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__);
+ *tty->termios = *old_termios;
+ dev_err(&edge_port->port->dev, "%s - out of memory\n",
+ __func__);
return;
}
@@ -2427,22 +2304,22 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
config->bUartMode = (__u8)(edge_port->bUartMode);
switch (cflag & CSIZE) {
- case CS5:
- config->bDataBits = UMP_UART_CHAR5BITS;
- dbg ("%s - data bits = 5", __func__);
- break;
- case CS6:
- config->bDataBits = UMP_UART_CHAR6BITS;
- dbg ("%s - data bits = 6", __func__);
- break;
- case CS7:
- config->bDataBits = UMP_UART_CHAR7BITS;
- dbg ("%s - data bits = 7", __func__);
- break;
- default:
- case CS8:
- config->bDataBits = UMP_UART_CHAR8BITS;
- dbg ("%s - data bits = 8", __func__);
+ case CS5:
+ config->bDataBits = UMP_UART_CHAR5BITS;
+ dbg("%s - data bits = 5", __func__);
+ break;
+ case CS6:
+ config->bDataBits = UMP_UART_CHAR6BITS;
+ dbg("%s - data bits = 6", __func__);
+ break;
+ case CS7:
+ config->bDataBits = UMP_UART_CHAR7BITS;
+ dbg("%s - data bits = 7", __func__);
+ break;
+ default:
+ case CS8:
+ config->bDataBits = UMP_UART_CHAR8BITS;
+ dbg("%s - data bits = 8", __func__);
break;
}
@@ -2457,7 +2334,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
dbg("%s - parity = even", __func__);
}
} else {
- config->bParity = UMP_UART_NOPARITY;
+ config->bParity = UMP_UART_NOPARITY;
dbg("%s - parity = none", __func__);
}
@@ -2480,29 +2357,26 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
restart_read(edge_port);
}
- /* if we are implementing XON/XOFF, set the start and stop character in the device */
- if (I_IXOFF(tty) || I_IXON(tty)) {
- config->cXon = START_CHAR(tty);
- config->cXoff = STOP_CHAR(tty);
+ /* if we are implementing XON/XOFF, set the start and stop
+ character in the device */
+ config->cXon = START_CHAR(tty);
+ config->cXoff = STOP_CHAR(tty);
- /* if we are implementing INBOUND XON/XOFF */
- if (I_IXOFF(tty)) {
- config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
- dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, config->cXon, config->cXoff);
- } else {
- dbg ("%s - INBOUND XON/XOFF is disabled", __func__);
- }
+ /* if we are implementing INBOUND XON/XOFF */
+ if (I_IXOFF(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
+ dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, config->cXon, config->cXoff);
+ } else
+ dbg("%s - INBOUND XON/XOFF is disabled", __func__);
- /* if we are implementing OUTBOUND XON/XOFF */
- if (I_IXON(tty)) {
- config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
- dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
- __func__, config->cXon, config->cXoff);
- } else {
- dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__);
- }
- }
+ /* if we are implementing OUTBOUND XON/XOFF */
+ if (I_IXON(tty)) {
+ config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
+ dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+ __func__, config->cXon, config->cXoff);
+ } else
+ dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
tty->termios->c_cflag &= ~CMSPAR;
@@ -2519,41 +2393,36 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
/* FIXME: Recompute actual baud from divisor here */
- dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
+ dbg("%s - baud rate = %d, wBaudRate = %d", __func__, baud,
+ config->wBaudRate);
- dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate));
- dbg ("wFlags: 0x%x", config->wFlags);
- dbg ("bDataBits: %d", config->bDataBits);
- dbg ("bParity: %d", config->bParity);
- dbg ("bStopBits: %d", config->bStopBits);
- dbg ("cXon: %d", config->cXon);
- dbg ("cXoff: %d", config->cXoff);
- dbg ("bUartMode: %d", config->bUartMode);
+ dbg("wBaudRate: %d", (int)(461550L / config->wBaudRate));
+ dbg("wFlags: 0x%x", config->wFlags);
+ dbg("bDataBits: %d", config->bDataBits);
+ dbg("bParity: %d", config->bParity);
+ dbg("bStopBits: %d", config->bStopBits);
+ dbg("cXon: %d", config->cXon);
+ dbg("cXoff: %d", config->cXoff);
+ dbg("bUartMode: %d", config->bUartMode);
/* move the word values into big endian mode */
- cpu_to_be16s (&config->wFlags);
- cpu_to_be16s (&config->wBaudRate);
+ cpu_to_be16s(&config->wFlags);
+ cpu_to_be16s(&config->wBaudRate);
- status = TIWriteCommandSync (edge_port->port->serial->dev,
- UMPC_SET_CONFIG,
+ status = send_cmd(edge_port->port->serial->dev, UMPC_SET_CONFIG,
(__u8)(UMPM_UART1_PORT + port_number),
- 0,
- (__u8 *)config,
- sizeof(*config));
- if (status) {
- dbg ("%s - error %d when trying to write config to device",
+ 0, (__u8 *)config, sizeof(*config));
+ if (status)
+ dbg("%s - error %d when trying to write config to device",
__func__, status);
- }
-
- kfree (config);
-
+ kfree(config);
return;
}
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int cflag;
cflag = tty->termios->c_cflag;
@@ -2562,20 +2431,19 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
tty->termios->c_cflag, tty->termios->c_iflag);
dbg("%s - old clfag %08x old iflag %08x", __func__,
old_termios->c_cflag, old_termios->c_iflag);
-
dbg("%s - port %d", __func__, port->number);
if (edge_port == NULL)
return;
-
/* change the port settings to the new ones specified */
- change_port_settings (edge_port, old_termios);
-
+ change_port_settings(tty, edge_port, old_termios);
return;
}
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
unsigned long flags;
@@ -2601,13 +2469,13 @@ static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsig
edge_port->shadow_mcr = mcr;
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
- TIRestoreMCR (edge_port, mcr);
-
+ restore_mcr(edge_port, mcr);
return 0;
}
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr;
@@ -2634,7 +2502,8 @@ static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
+static int get_serial_info(struct edgeport_port *edge_port,
+ struct serial_struct __user *retinfo)
{
struct serial_struct tmp;
@@ -2652,18 +2521,16 @@ static int get_serial_info (struct edgeport_port *edge_port, struct serial_struc
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
tmp.closing_wait = closing_wait;
-// tmp.custom_divisor = state->custom_divisor;
-// tmp.hub6 = state->hub6;
-// tmp.io_type = state->io_type;
-
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
return 0;
}
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
@@ -2671,81 +2538,64 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCINQ:
- dbg("%s - (%d) TIOCINQ", __func__, port->number);
-// return get_number_bytes_avail(edge_port, (unsigned int *) arg);
- break;
-
- case TIOCSERGETLSR:
- dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number);
-// return get_lsr_info(edge_port, (unsigned int *) arg);
- break;
-
- case TIOCGSERIAL:
- dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
- return get_serial_info(edge_port, (struct serial_struct __user *) arg);
- break;
-
- case TIOCSSERIAL:
- dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
- break;
-
- case TIOCMIWAIT:
- dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
- cprev = edge_port->icount;
- while (1) {
- interruptible_sleep_on(&edge_port->delta_msr_wait);
- /* see if a signal did it */
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = edge_port->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
+ case TIOCGSERIAL:
+ dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ return get_serial_info(edge_port,
+ (struct serial_struct __user *) arg);
+ case TIOCMIWAIT:
+ dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = edge_port->icount;
+ while (1) {
+ interruptible_sleep_on(&edge_port->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = edge_port->icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ return 0;
}
- /* not reached */
- break;
-
- case TIOCGICOUNT:
- dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
- port->number, edge_port->icount.rx, edge_port->icount.tx);
- if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
- return -EFAULT;
- return 0;
+ cprev = cnow;
+ }
+ /* not reached */
+ break;
+ case TIOCGICOUNT:
+ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+ port->number, edge_port->icount.rx, edge_port->icount.tx);
+ if (copy_to_user((void __user *)arg, &edge_port->icount,
+ sizeof(edge_port->icount)))
+ return -EFAULT;
+ return 0;
}
-
return -ENOIOCTLCMD;
}
-static void edge_break (struct usb_serial_port *port, int break_state)
+static void edge_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
+ int bv = 0; /* Off */
- dbg ("%s - state = %d", __func__, break_state);
+ dbg("%s - state = %d", __func__, break_state);
/* chase the port close */
- TIChasePort (edge_port, 0, 0);
+ chase_port(edge_port, 0, 0);
- if (break_state == -1) {
- status = TISetBreak (edge_port);
- } else {
- status = TIClearBreak (edge_port);
- }
- if (status) {
- dbg ("%s - error %d sending break set/clear command.",
+ if (break_state == -1)
+ bv = 1; /* On */
+ status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
+ if (status)
+ dbg("%s - error %d sending break set/clear command.",
__func__, status);
- }
}
-static int edge_startup (struct usb_serial *serial)
+static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
@@ -2765,9 +2615,9 @@ static int edge_startup (struct usb_serial *serial)
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
- status = TIDownloadFirmware (edge_serial);
+ status = download_fw(edge_serial);
if (status) {
- kfree (edge_serial);
+ kfree(edge_serial);
return status;
}
@@ -2775,13 +2625,15 @@ static int edge_startup (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
goto cleanup;
}
spin_lock_init(&edge_port->ep_lock);
edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
if (edge_port->ep_out_buf == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+ dev_err(&serial->dev->dev, "%s - Out of memory\n",
+ __func__);
kfree(edge_port);
goto cleanup;
}
@@ -2790,27 +2642,27 @@ static int edge_startup (struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], edge_port);
edge_port->bUartMode = default_uart_mode;
}
-
+
return 0;
cleanup:
- for (--i; i>=0; --i) {
+ for (--i; i >= 0; --i) {
edge_port = usb_get_serial_port_data(serial->port[i]);
edge_buf_free(edge_port->ep_out_buf);
kfree(edge_port);
usb_set_serial_port_data(serial->port[i], NULL);
}
- kfree (edge_serial);
+ kfree(edge_serial);
usb_set_serial_data(serial, NULL);
return -ENOMEM;
}
-static void edge_shutdown (struct usb_serial *serial)
+static void edge_shutdown(struct usb_serial *serial)
{
int i;
struct edgeport_port *edge_port;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
for (i = 0; i < serial->num_ports; ++i) {
edge_port = usb_get_serial_port_data(serial->port[i]);
@@ -2852,7 +2704,8 @@ static ssize_t store_uart_mode(struct device *dev,
return count;
}
-static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode);
+static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode,
+ store_uart_mode);
static int edge_create_sysfs_attrs(struct usb_serial_port *port)
{
@@ -2922,9 +2775,9 @@ static void edge_buf_free(struct edge_buf *eb)
static void edge_buf_clear(struct edge_buf *eb)
{
- if (eb != NULL)
- eb->buf_get = eb->buf_put;
- /* equivalent to a get of all data available */
+ if (eb != NULL)
+ eb->buf_get = eb->buf_put;
+ /* equivalent to a get of all data available */
}
@@ -2937,10 +2790,9 @@ static void edge_buf_clear(struct edge_buf *eb)
static unsigned int edge_buf_data_avail(struct edge_buf *eb)
{
- if (eb != NULL)
- return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
- else
+ if (eb == NULL)
return 0;
+ return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
}
@@ -2953,10 +2805,9 @@ static unsigned int edge_buf_data_avail(struct edge_buf *eb)
static unsigned int edge_buf_space_avail(struct edge_buf *eb)
{
- if (eb != NULL)
- return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
- else
+ if (eb == NULL)
return 0;
+ return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
}
@@ -3113,7 +2964,7 @@ static int __init edgeport_init(void)
if (retval)
goto failed_2port_device_register;
retval = usb_register(&io_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
@@ -3125,11 +2976,11 @@ failed_1port_device_register:
return retval;
}
-static void __exit edgeport_exit (void)
+static void __exit edgeport_exit(void)
{
- usb_deregister (&io_driver);
- usb_serial_deregister (&edgeport_1port_device);
- usb_serial_deregister (&edgeport_2port_device);
+ usb_deregister(&io_driver);
+ usb_serial_deregister(&edgeport_1port_device);
+ usb_serial_deregister(&edgeport_2port_device);
}
module_init(edgeport_init);
@@ -3151,8 +3002,8 @@ module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
+MODULE_PARM_DESC(ignore_cpu_rev,
+ "Ignore the cpu revision when connecting to a device");
module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
-
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d9fb3768a2d..832a5a4f3cb 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -53,7 +53,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "ipaq.h"
@@ -74,19 +74,21 @@ static int connect_retries = KP_RETRIES;
static int initial_wait;
/* Function prototypes for an ipaq */
-static int ipaq_open (struct usb_serial_port *port, struct file *filp);
-static void ipaq_close (struct usb_serial_port *port, struct file *filp);
-static int ipaq_startup (struct usb_serial *serial);
-static void ipaq_shutdown (struct usb_serial *serial);
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
- int count);
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
- int count);
+static int ipaq_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int ipaq_startup(struct usb_serial *serial);
+static void ipaq_shutdown(struct usb_serial *serial);
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int ipaq_write_bulk(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
static void ipaq_write_gather(struct usb_serial_port *port);
-static void ipaq_read_bulk_callback (struct urb *urb);
+static void ipaq_read_bulk_callback(struct urb *urb);
static void ipaq_write_bulk_callback(struct urb *urb);
-static int ipaq_write_room(struct usb_serial_port *port);
-static int ipaq_chars_in_buffer(struct usb_serial_port *port);
+static int ipaq_write_room(struct tty_struct *tty);
+static int ipaq_chars_in_buffer(struct tty_struct *tty);
static void ipaq_destroy_lists(struct usb_serial_port *port);
@@ -550,7 +552,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, ipaq_id_table);
+MODULE_DEVICE_TABLE(usb, ipaq_id_table);
static struct usb_driver ipaq_driver = {
.name = "ipaq",
@@ -591,7 +593,8 @@ static spinlock_t write_list_lock;
static int bytes_in;
static int bytes_out;
-static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+static int ipaq_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct ipaq_private *priv;
@@ -617,9 +620,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
- if (pkt == NULL) {
+ if (pkt == NULL)
goto enomem;
- }
+
pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
if (pkt->data == NULL) {
kfree(pkt);
@@ -637,21 +640,24 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
* discipline instead of queueing.
*/
- port->tty->low_latency = 1;
- port->tty->raw = 1;
- port->tty->real_raw = 1;
-
+ if (tty) {
+ tty->low_latency = 1;
+ /* FIXME: These two are bogus */
+ tty->raw = 1;
+ tty->real_raw = 1;
+ }
/*
* Lose the small buffers usbserial provides. Make larger ones.
*/
kfree(port->bulk_in_buffer);
- kfree(port->bulk_out_buffer);
port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
if (port->bulk_in_buffer == NULL) {
port->bulk_out_buffer = NULL; /* prevent double free */
goto enomem;
}
+
+ kfree(port->bulk_out_buffer);
port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
if (port->bulk_out_buffer == NULL) {
kfree(port->bulk_in_buffer);
@@ -661,8 +667,9 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
port->read_urb->transfer_buffer = port->bulk_in_buffer;
port->write_urb->transfer_buffer = port->bulk_out_buffer;
port->read_urb->transfer_buffer_length = URBDATA_SIZE;
- port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
-
+ port->bulk_out_size = port->write_urb->transfer_buffer_length
+ = URBDATA_SIZE;
+
msleep(1000*initial_wait);
/*
@@ -691,13 +698,15 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ipaq_read_bulk_callback, port);
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting read urb, error %d", __func__, result);
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
goto error;
}
@@ -713,12 +722,13 @@ error:
}
-static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
-
+
/*
* shut down bulk read and write
*/
@@ -728,7 +738,8 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
kfree(priv);
usb_set_serial_port_data(port, NULL);
- /* Uncomment the following line if you want to see some statistics in your syslog */
+ /* Uncomment the following line if you want to see some statistics
+ * in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
}
@@ -748,9 +759,10 @@ static void ipaq_read_bulk_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -759,18 +771,20 @@ static void ipaq_read_bulk_callback(struct urb *urb)
}
/* Continue trying to always read */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ipaq_read_bulk_callback, port);
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
return;
}
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
const unsigned char *current_position = buf;
int bytes_sent = 0;
@@ -780,9 +794,8 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
while (count > 0) {
transfer_size = min(count, PACKET_SIZE);
- if (ipaq_write_bulk(port, current_position, transfer_size)) {
+ if (ipaq_write_bulk(port, current_position, transfer_size))
break;
- }
current_position += transfer_size;
bytes_sent += transfer_size;
count -= transfer_size;
@@ -790,10 +803,10 @@ static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
}
return bytes_sent;
-}
+}
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int ipaq_write_bulk(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct ipaq_private *priv = usb_get_serial_port_data(port);
struct ipaq_packet *pkt = NULL;
@@ -830,9 +843,9 @@ static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *bu
ipaq_write_gather(port);
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
- }
+ if (result)
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else {
spin_unlock_irqrestore(&write_list_lock, flags);
}
@@ -859,16 +872,15 @@ static void ipaq_write_gather(struct usb_serial_port *port)
list_move(&pkt->list, &priv->freelist);
priv->free_len += PACKET_SIZE;
}
- if (room == 0) {
+ if (room == 0)
break;
- }
}
count = URBDATA_SIZE - room;
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->write_urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ipaq_write_bulk_callback, port);
return;
}
@@ -893,9 +905,9 @@ static void ipaq_write_bulk_callback(struct urb *urb)
ipaq_write_gather(port);
spin_unlock_irqrestore(&write_list_lock, flags);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
- }
+ if (result)
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else {
priv->active = 0;
spin_unlock_irqrestore(&write_list_lock, flags);
@@ -904,16 +916,18 @@ static void ipaq_write_bulk_callback(struct urb *urb)
usb_serial_port_softint(port);
}
-static int ipaq_write_room(struct usb_serial_port *port)
+static int ipaq_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - freelen %d", __func__, priv->free_len);
return priv->free_len;
}
-static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+static int ipaq_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - queuelen %d", __func__, priv->queue_len);
@@ -944,7 +958,7 @@ static int ipaq_startup(struct usb_serial *serial)
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
- return usb_reset_configuration (serial->dev);
+ return usb_reset_configuration(serial->dev);
}
static void ipaq_shutdown(struct usb_serial *serial)
@@ -957,7 +971,7 @@ static int __init ipaq_init(void)
int retval;
spin_lock_init(&write_list_lock);
retval = usb_serial_register(&ipaq_device);
- if (retval)
+ if (retval)
goto failed_usb_serial_register;
info(DRIVER_DESC " " DRIVER_VERSION);
if (vendor) {
@@ -967,7 +981,7 @@ static int __init ipaq_init(void)
retval = usb_register(&ipaq_driver);
if (retval)
goto failed_usb_register;
-
+
return 0;
failed_usb_register:
usb_serial_deregister(&ipaq_device);
@@ -986,8 +1000,8 @@ static void __exit ipaq_exit(void)
module_init(ipaq_init);
module_exit(ipaq_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
@@ -1000,7 +1014,9 @@ module_param(product, ushort, 0);
MODULE_PARM_DESC(product, "User specified USB idProduct");
module_param(connect_retries, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)");
+MODULE_PARM_DESC(connect_retries,
+ "Maximum number of connect retries (one second each)");
module_param(initial_wait, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)");
+MODULE_PARM_DESC(initial_wait,
+ "Time to wait before attempting a connection (in seconds)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index bc85ca5c1c3..a842025b9b5 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -10,27 +10,27 @@
* (at your option) any later version.
*
* All information about the device was acquired using SnoopyPro
- * on MSFT's O/S, and examing the MSFT drivers' debug output
+ * on MSFT's O/S, and examing the MSFT drivers' debug output
* (insanely left _on_ in the enduser version)
*
* It was written out of frustration with the IPWireless USB modem
* supplied by Axity3G/Sentech South Africa not supporting
* Linux whatsoever.
*
- * Nobody provided any proprietary information that was not already
+ * Nobody provided any proprietary information that was not already
* available for this device.
- *
- * The modem adheres to the "3GPP TS 27.007 AT command set for 3G
- * User Equipment (UE)" standard, available from
+ *
+ * The modem adheres to the "3GPP TS 27.007 AT command set for 3G
+ * User Equipment (UE)" standard, available from
* http://www.3gpp.org/ftp/Specs/html-info/27007.htm
*
* The code was only tested the IPWireless handheld modem distributed
* in South Africa by Sentech.
- *
+ *
* It may work for Woosh Inc in .nz too, as it appears they use the
* same kit.
*
- * There is still some work to be done in terms of handling
+ * There is still some work to be done in terms of handling
* DCD, DTR, RTS, CTS which are currently faked.
* It's good enough for PPP at this point. It's based off all kinds of
* code found in usb/serial and usb/class
@@ -47,7 +47,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
* Version Information
@@ -64,7 +64,7 @@
/* Message sizes */
#define EVENT_BUFFER_SIZE 0xFF
-#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
+#define CHAR2INT16(c1, c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
#define NUM_BULK_URBS 24
#define NUM_CONTROL_URBS 16
@@ -94,33 +94,34 @@ enum {
/* data bits */
#define ipw_dtb_7 0x700
-#define ipw_dtb_8 0x810 // ok so the define is misleading, I know, but forces 8,n,1
- // I mean, is there a point to any other setting these days? :)
+#define ipw_dtb_8 0x810 /* ok so the define is misleading, I know, but forces 8,n,1 */
+ /* I mean, is there a point to any other setting these days? :) */
/* usb control request types : */
-#define IPW_SIO_RXCTL 0x00 // control bulk rx channel transmissions, value=1/0 (on/off)
-#define IPW_SIO_SET_BAUD 0x01 // set baud, value=requested ipw_sio_bxxxx
-#define IPW_SIO_SET_LINE 0x03 // set databits, parity. value=ipw_dtb_x
-#define IPW_SIO_SET_PIN 0x03 // set/clear dtr/rts value=ipw_pin_xxx
-#define IPW_SIO_POLL 0x08 // get serial port status byte, call with value=0
-#define IPW_SIO_INIT 0x11 // initializes ? value=0 (appears as first thing todo on open)
-#define IPW_SIO_PURGE 0x12 // purge all transmissions?, call with value=numchar_to_purge
-#define IPW_SIO_HANDFLOW 0x13 // set xon/xoff limits value=0, and a buffer of 0x10 bytes
-#define IPW_SIO_SETCHARS 0x13 // set the flowcontrol special chars, value=0, buf=6 bytes,
- // last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13
+#define IPW_SIO_RXCTL 0x00 /* control bulk rx channel transmissions, value=1/0 (on/off) */
+#define IPW_SIO_SET_BAUD 0x01 /* set baud, value=requested ipw_sio_bxxxx */
+#define IPW_SIO_SET_LINE 0x03 /* set databits, parity. value=ipw_dtb_x */
+#define IPW_SIO_SET_PIN 0x03 /* set/clear dtr/rts value=ipw_pin_xxx */
+#define IPW_SIO_POLL 0x08 /* get serial port status byte, call with value=0 */
+#define IPW_SIO_INIT 0x11 /* initializes ? value=0 (appears as first thing todo on open) */
+#define IPW_SIO_PURGE 0x12 /* purge all transmissions?, call with value=numchar_to_purge */
+#define IPW_SIO_HANDFLOW 0x13 /* set xon/xoff limits value=0, and a buffer of 0x10 bytes */
+#define IPW_SIO_SETCHARS 0x13 /* set the flowcontrol special chars, value=0, buf=6 bytes, */
+ /* last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 */
/* values used for request IPW_SIO_SET_PIN */
#define IPW_PIN_SETDTR 0x101
#define IPW_PIN_SETRTS 0x202
#define IPW_PIN_CLRDTR 0x100
-#define IPW_PIN_CLRRTS 0x200 // unconfirmed
+#define IPW_PIN_CLRRTS 0x200 /* unconfirmed */
/* values used for request IPW_SIO_RXCTL */
#define IPW_RXBULK_ON 1
#define IPW_RXBULK_OFF 0
/* various 16 byte hardcoded transferbuffers used by flow control */
-#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define IPW_BYTES_FLOWINIT { 0x01, 0, 0, 0, 0x40, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
/* Interpretation of modem status lines */
/* These need sorting out by individually connecting pins and checking
@@ -132,17 +133,6 @@ enum {
#define IPW_CTS ((1<<5) | (1<<4))
#define IPW_WANTS_TO_SEND 0x30
-//#define IPW_DTR /* Data Terminal Ready */
-//#define IPW_CTS /* Clear To Send */
-//#define IPW_CD /* Carrier Detect */
-//#define IPW_DSR /* Data Set Ready */
-//#define IPW_RxD /* Receive pin */
-
-//#define IPW_LE
-//#define IPW_RTS
-//#define IPW_ST
-//#define IPW_SR
-//#define IPW_RI /* Ring Indicator */
static struct usb_device_id usb_ipw_ids[] = {
{ USB_DEVICE(IPW_VID, IPW_PID) },
@@ -177,9 +167,10 @@ static void ipw_read_bulk_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -187,19 +178,22 @@ static void ipw_read_bulk_callback(struct urb *urb)
}
/* Continue trying to always read */
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- ipw_read_bulk_callback, port);
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ipw_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
return;
}
-static int ipw_open(struct usb_serial_port *port, struct file *filp)
+static int ipw_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_device *dev = port->serial->dev;
u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT;
@@ -212,29 +206,33 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
if (!buf_flow_init)
return -ENOMEM;
- if (port->tty)
- port->tty->low_latency = 1;
-
- /* --1: Tell the modem to initialize (we think) From sniffs this is always the
- * first thing that gets sent to the modem during opening of the device */
- dbg("%s: Sending SIO_INIT (we guess)",__func__);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
- IPW_SIO_INIT,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0,
- 0, /* index */
- NULL,
- 0,
- 100000);
+ if (tty)
+ tty->low_latency = 1;
+
+ /* --1: Tell the modem to initialize (we think) From sniffs this is
+ * always the first thing that gets sent to the modem during
+ * opening of the device */
+ dbg("%s: Sending SIO_INIT (we guess)", __func__);
+ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ IPW_SIO_INIT,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
if (result < 0)
- dev_err(&port->dev, "Init of modem failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "Init of modem failed (error = %d)\n", result);
/* reset the bulk pipes */
- usb_clear_halt(dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
- usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+ usb_clear_halt(dev,
+ usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
+ usb_clear_halt(dev,
+ usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
- /*--2: Start reading from the device */
- dbg("%s: setting up bulk read callback",__func__);
+ /*--2: Start reading from the device */
+ dbg("%s: setting up bulk read callback", __func__);
usb_fill_bulk_urb(port->read_urb, dev,
usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
port->bulk_in_buffer,
@@ -242,66 +240,72 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
ipw_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result < 0)
- dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
+ dbg("%s - usb_submit_urb(read bulk) failed with status %d",
+ __func__, result);
/*--3: Tell the modem to open the floodgates on the rx bulk channel */
- dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
+ dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_RXCTL,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_RXBULK_ON,
- 0, /* index */
- NULL,
- 0,
- 100000);
- if (result < 0)
- dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
+ IPW_SIO_RXCTL,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_RXBULK_ON,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
+ if (result < 0)
+ dev_err(&port->dev,
+ "Enabling bulk RxRead failed (error = %d)\n", result);
/*--4: setup the initial flowcontrol */
- dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
+ dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_HANDFLOW,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0,
- 0,
- buf_flow_init,
- 0x10,
- 200000);
+ IPW_SIO_HANDFLOW,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0,
+ 0,
+ buf_flow_init,
+ 0x10,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "initial flowcontrol failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "initial flowcontrol failed (error = %d)\n", result);
/*--5: raise the dtr */
- dbg("%s:raising dtr",__func__);
+ dbg("%s:raising dtr", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_SETDTR,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_SETDTR,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "setting dtr failed (error = %d)\n", result);
/*--6: raise the rts */
- dbg("%s:raising rts",__func__);
+ dbg("%s:raising rts", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_SETRTS,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_SETRTS,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
-
+ dev_err(&port->dev,
+ "setting dtr failed (error = %d)\n", result);
+
kfree(buf_flow_init);
return 0;
}
-static void ipw_close(struct usb_serial_port *port, struct file * filp)
+static void ipw_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_device *dev = port->serial->dev;
int result;
@@ -312,56 +316,62 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
}
/*--1: drop the dtr */
- dbg("%s:dropping dtr",__func__);
+ dbg("%s:dropping dtr", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRDTR,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_CLRDTR,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
+ dev_err(&port->dev, "dropping dtr failed (error = %d)\n",
+ result);
/*--2: drop the rts */
- dbg("%s:dropping rts",__func__);
+ dbg("%s:dropping rts", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_PIN_CLRRTS,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_PIN_CLRRTS,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
- dev_err(&port->dev, "dropping rts failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "dropping rts failed (error = %d)\n", result);
/*--3: purge */
- dbg("%s:sending purge",__func__);
+ dbg("%s:sending purge", __func__);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- 0x03,
- 0,
- NULL,
- 0,
- 200000);
+ IPW_SIO_PURGE, USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE | USB_DIR_OUT,
+ 0x03,
+ 0,
+ NULL,
+ 0,
+ 200000);
if (result < 0)
dev_err(&port->dev, "purge failed (error = %d)\n", result);
- /* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */
+ /* send RXBULK_off (tell modem to stop transmitting bulk data on
+ rx chan) */
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- IPW_SIO_RXCTL,
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- IPW_RXBULK_OFF,
- 0, /* index */
- NULL,
- 0,
- 100000);
+ IPW_SIO_RXCTL,
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ IPW_RXBULK_OFF,
+ 0, /* index */
+ NULL,
+ 0,
+ 100000);
if (result < 0)
- dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)\n", result);
+ dev_err(&port->dev,
+ "Disabling bulk RxRead failed (error = %d)\n", result);
/* shutdown any in-flight urbs that we know about */
usb_kill_urb(port->read_urb);
@@ -384,13 +394,14 @@ static void ipw_write_bulk_callback(struct urb *urb)
usb_serial_port_softint(port);
}
-static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct usb_device *dev = port->serial->dev;
int ret;
dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
- count, in_interrupt() );
+ count, in_interrupt());
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
@@ -421,13 +432,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (ret != 0) {
port->write_urb_busy = 0;
- dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
+ dbg("%s - usb_submit_urb(write bulk) failed with error = %d",
+ __func__, ret);
return ret;
}
dbg("%s returning %d", __func__, count);
return count;
-}
+}
static int ipw_probe(struct usb_serial_port *port)
{
@@ -486,8 +498,8 @@ module_init(usb_ipw_init);
module_exit(usb_ipw_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 004d57385a7..e59155c6607 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -19,7 +19,12 @@
* was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli
* <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com>
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
+ * 2008_Jun_02 Felipe Balbi <me@felipebalbi.com>
+ * Introduced common header to be used also in USB Gadget Framework.
+ * Still needs some other style fixes.
*
* 2007_Jun_21 Alan Cox <alan@redhat.com>
* Minimal cleanups for some of the driver problens and tty layer abuse.
@@ -59,9 +64,10 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/usb/irda.h>
/*
* Version Information
@@ -70,100 +76,77 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB IR Dongle driver"
-/* USB IrDA class spec information */
-#define USB_CLASS_IRDA 0x02
-#define USB_DT_IRDA 0x21
-#define IU_REQ_GET_CLASS_DESC 0x06
-#define SPEED_2400 0x01
-#define SPEED_9600 0x02
-#define SPEED_19200 0x03
-#define SPEED_38400 0x04
-#define SPEED_57600 0x05
-#define SPEED_115200 0x06
-#define SPEED_576000 0x07
-#define SPEED_1152000 0x08
-#define SPEED_4000000 0x09
-
-struct irda_class_desc {
- u8 bLength;
- u8 bDescriptorType;
- u16 bcdSpecRevision;
- u8 bmDataSize;
- u8 bmWindowSize;
- u8 bmMinTurnaroundTime;
- u16 wBaudRate;
- u8 bmAdditionalBOFs;
- u8 bIrdaRateSniff;
- u8 bMaxUnicastList;
-} __attribute__ ((packed));
-
static int debug;
/* if overridden by the user, then use their value for the size of the read and
* write urbs */
static int buffer_size;
+
/* if overridden by the user, then use the specified number of XBOFs */
static int xbof = -1;
static int ir_startup (struct usb_serial *serial);
-static int ir_open (struct usb_serial_port *port, struct file *filep);
-static void ir_close (struct usb_serial_port *port, struct file *filep);
-static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
+static int ir_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filep);
+static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filep);
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
static void ir_write_bulk_callback (struct urb *urb);
static void ir_read_bulk_callback (struct urb *urb);
-static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
+static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
/* Not that this lot means you can only have one per system */
-static u8 ir_baud = 0;
-static u8 ir_xbof = 0;
-static u8 ir_add_bof = 0;
+static u8 ir_baud;
+static u8 ir_xbof;
+static u8 ir_add_bof;
-static struct usb_device_id id_table [] = {
+static struct usb_device_id ir_id_table[] = {
{ USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */
{ USB_DEVICE(0x08e9, 0x0100) }, /* XTNDAccess */
{ USB_DEVICE(0x09c4, 0x0011) }, /* ACTiSys ACT-IR2000U */
- { USB_INTERFACE_INFO (USB_CLASS_APP_SPEC, USB_CLASS_IRDA, 0) },
+ { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, ir_id_table);
static struct usb_driver ir_driver = {
- .name = "ir-usb",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
- .no_dynamic_id = 1,
+ .name = "ir-usb",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = ir_id_table,
+ .no_dynamic_id = 1,
};
-
static struct usb_serial_driver ir_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "ir-usb",
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ir-usb",
},
- .description = "IR Dongle",
- .usb_driver = &ir_driver,
- .id_table = id_table,
- .num_ports = 1,
- .set_termios = ir_set_termios,
- .attach = ir_startup,
- .open = ir_open,
- .close = ir_close,
- .write = ir_write,
- .write_bulk_callback = ir_write_bulk_callback,
- .read_bulk_callback = ir_read_bulk_callback,
+ .description = "IR Dongle",
+ .usb_driver = &ir_driver,
+ .id_table = ir_id_table,
+ .num_ports = 1,
+ .set_termios = ir_set_termios,
+ .attach = ir_startup,
+ .open = ir_open,
+ .close = ir_close,
+ .write = ir_write,
+ .write_bulk_callback = ir_write_bulk_callback,
+ .read_bulk_callback = ir_read_bulk_callback,
};
-static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
+static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
{
dbg("bLength=%x", desc->bLength);
dbg("bDescriptorType=%x", desc->bDescriptorType);
- dbg("bcdSpecRevision=%x", desc->bcdSpecRevision);
+ dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
dbg("bmDataSize=%x", desc->bmDataSize);
dbg("bmWindowSize=%x", desc->bmWindowSize);
dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
- dbg("wBaudRate=%x", desc->wBaudRate);
+ dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
@@ -181,35 +164,37 @@ static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
*
* Based on the same function in drivers/net/irda/irda-usb.c
*/
-static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
+static struct usb_irda_cs_descriptor *
+irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
{
- struct irda_class_desc *desc;
+ struct usb_irda_cs_descriptor *desc;
int ret;
-
- desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
- if (desc == NULL)
+
+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+ if (!desc)
return NULL;
-
- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
- IU_REQ_GET_CLASS_DESC,
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_CS_IRDA_GET_CLASS_DESC,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, ifnum, desc, sizeof(*desc), 1000);
-
+
dbg("%s - ret=%d", __func__, ret);
if (ret < sizeof(*desc)) {
dbg("%s - class descriptor read %s (%d)",
__func__,
- (ret<0) ? "failed" : "too short",
+ (ret < 0) ? "failed" : "too short",
ret);
goto error;
}
- if (desc->bDescriptorType != USB_DT_IRDA) {
+ if (desc->bDescriptorType != USB_DT_CS_IRDA) {
dbg("%s - bad class descriptor type", __func__);
goto error;
}
-
+
irda_usb_dump_class_desc(desc);
return desc;
+
error:
kfree(desc);
return NULL;
@@ -219,64 +204,101 @@ error:
static u8 ir_xbof_change(u8 xbof)
{
u8 result;
+
/* reference irda-usb.c */
- switch(xbof) {
- case 48: result = 0x10; break;
- case 28:
- case 24: result = 0x20; break;
- default:
- case 12: result = 0x30; break;
- case 5:
- case 6: result = 0x40; break;
- case 3: result = 0x50; break;
- case 2: result = 0x60; break;
- case 1: result = 0x70; break;
- case 0: result = 0x80; break;
+ switch (xbof) {
+ case 48:
+ result = 0x10;
+ break;
+ case 28:
+ case 24:
+ result = 0x20;
+ break;
+ default:
+ case 12:
+ result = 0x30;
+ break;
+ case 5:
+ case 6:
+ result = 0x40;
+ break;
+ case 3:
+ result = 0x50;
+ break;
+ case 2:
+ result = 0x60;
+ break;
+ case 1:
+ result = 0x70;
+ break;
+ case 0:
+ result = 0x80;
+ break;
}
+
return(result);
}
-static int ir_startup (struct usb_serial *serial)
+static int ir_startup(struct usb_serial *serial)
{
- struct irda_class_desc *irda_desc;
+ struct usb_irda_cs_descriptor *irda_desc;
- irda_desc = irda_usb_find_class_desc (serial->dev, 0);
- if (irda_desc == NULL) {
- dev_err (&serial->dev->dev, "IRDA class descriptor not found, device not bound\n");
+ irda_desc = irda_usb_find_class_desc(serial->dev, 0);
+ if (!irda_desc) {
+ dev_err(&serial->dev->dev,
+ "IRDA class descriptor not found, device not bound\n");
return -ENODEV;
}
- dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+ dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
__func__,
- (irda_desc->wBaudRate & 0x0001) ? " 2400" : "",
- (irda_desc->wBaudRate & 0x0002) ? " 9600" : "",
- (irda_desc->wBaudRate & 0x0004) ? " 19200" : "",
- (irda_desc->wBaudRate & 0x0008) ? " 38400" : "",
- (irda_desc->wBaudRate & 0x0010) ? " 57600" : "",
- (irda_desc->wBaudRate & 0x0020) ? " 115200" : "",
- (irda_desc->wBaudRate & 0x0040) ? " 576000" : "",
- (irda_desc->wBaudRate & 0x0080) ? " 1152000" : "",
- (irda_desc->wBaudRate & 0x0100) ? " 4000000" : "");
-
- switch( irda_desc->bmAdditionalBOFs ) {
- case 0x01: ir_add_bof = 48; break;
- case 0x02: ir_add_bof = 24; break;
- case 0x04: ir_add_bof = 12; break;
- case 0x08: ir_add_bof = 6; break;
- case 0x10: ir_add_bof = 3; break;
- case 0x20: ir_add_bof = 2; break;
- case 0x40: ir_add_bof = 1; break;
- case 0x80: ir_add_bof = 0; break;
- default:;
+ (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "",
+ (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : "");
+
+ switch (irda_desc->bmAdditionalBOFs) {
+ case USB_IRDA_AB_48:
+ ir_add_bof = 48;
+ break;
+ case USB_IRDA_AB_24:
+ ir_add_bof = 24;
+ break;
+ case USB_IRDA_AB_12:
+ ir_add_bof = 12;
+ break;
+ case USB_IRDA_AB_6:
+ ir_add_bof = 6;
+ break;
+ case USB_IRDA_AB_3:
+ ir_add_bof = 3;
+ break;
+ case USB_IRDA_AB_2:
+ ir_add_bof = 2;
+ break;
+ case USB_IRDA_AB_1:
+ ir_add_bof = 1;
+ break;
+ case USB_IRDA_AB_0:
+ ir_add_bof = 0;
+ break;
+ default:
+ break;
}
- kfree (irda_desc);
+ kfree(irda_desc);
- return 0;
+ return 0;
}
-static int ir_open (struct usb_serial_port *port, struct file *filp)
+static int ir_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
char *buffer;
int result = 0;
@@ -285,51 +307,56 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
if (buffer_size) {
/* override the default buffer sizes */
- buffer = kmalloc (buffer_size, GFP_KERNEL);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
- dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ dev_err(&port->dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
- kfree (port->read_urb->transfer_buffer);
+ kfree(port->read_urb->transfer_buffer);
port->read_urb->transfer_buffer = buffer;
port->read_urb->transfer_buffer_length = buffer_size;
- buffer = kmalloc (buffer_size, GFP_KERNEL);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!buffer) {
- dev_err (&port->dev, "%s - out of memory.\n", __func__);
+ dev_err(&port->dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
- kfree (port->write_urb->transfer_buffer);
+ kfree(port->write_urb->transfer_buffer);
port->write_urb->transfer_buffer = buffer;
port->write_urb->transfer_buffer_length = buffer_size;
port->bulk_out_size = buffer_size;
}
/* Start reading from the device */
- usb_fill_bulk_urb (
+ usb_fill_bulk_urb(
port->read_urb,
- port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
+ port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
ir_read_bulk_callback,
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
return result;
}
-static void ir_close (struct usb_serial_port *port, struct file * filp)
+static void ir_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file * filp)
{
dbg("%s - port %d", __func__, port->number);
-
+
/* shutdown our bulk read */
usb_kill_urb(port->read_urb);
}
-static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
unsigned char *transfer_buffer;
int result;
@@ -337,11 +364,6 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
dbg("%s - port = %d, count = %d", __func__, port->number, count);
- if (!port->tty) {
- dev_err (&port->dev, "%s - no tty???\n", __func__);
- return 0;
- }
-
if (count == 0)
return 0;
@@ -359,7 +381,7 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
/*
* The first byte of the packet we send to the device contains an
- * inband header which indicates an additional number of BOFs and
+ * inbound header which indicates an additional number of BOFs and
* a baud rate change.
*
* See section 5.4.2.2 of the USB IrDA spec.
@@ -367,9 +389,9 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
*transfer_buffer = ir_xbof | ir_baud;
++transfer_buffer;
- memcpy (transfer_buffer, buf, transfer_size);
+ memcpy(transfer_buffer, buf, transfer_size);
- usb_fill_bulk_urb (
+ usb_fill_bulk_urb(
port->write_urb,
port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -381,17 +403,19 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
port->write_urb->transfer_flags = URB_ZERO_PACKET;
- result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
port->write_urb_busy = 0;
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
} else
result = transfer_size;
return result;
}
-static void ir_write_bulk_callback (struct urb *urb)
+static void ir_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -405,7 +429,7 @@ static void ir_write_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data (
+ usb_serial_debug_data(
debug,
&port->dev,
__func__,
@@ -415,7 +439,7 @@ static void ir_write_bulk_callback (struct urb *urb)
usb_serial_port_softint(port);
}
-static void ir_read_bulk_callback (struct urb *urb)
+static void ir_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
@@ -425,74 +449,61 @@ static void ir_read_bulk_callback (struct urb *urb)
dbg("%s - port %d", __func__, port->number);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port closed.", __func__);
return;
}
switch (status) {
- case 0: /* Successful */
-
- /*
- * The first byte of the packet we get from the device
- * contains a busy indicator and baud rate change.
- * See section 5.4.1.2 of the USB IrDA spec.
- */
- if ((*data & 0x0f) > 0)
- ir_baud = *data & 0x0f;
-
- usb_serial_debug_data (
- debug,
- &port->dev,
- __func__,
- urb->actual_length,
- data);
-
- tty = port->tty;
-
- if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
- tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
- tty_flip_buffer_push(tty);
- }
-
- /*
- * No break here.
- * We want to resubmit the urb so we can read
- * again.
- */
+ case 0: /* Successful */
+ /*
+ * The first byte of the packet we get from the device
+ * contains a busy indicator and baud rate change.
+ * See section 5.4.1.2 of the USB IrDA spec.
+ */
+ if ((*data & 0x0f) > 0)
+ ir_baud = *data & 0x0f;
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
+ tty = port->port.tty;
+ if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
+ tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+ tty_flip_buffer_push(tty);
+ }
- case -EPROTO: /* taking inspiration from pl2303.c */
+ /*
+ * No break here.
+ * We want to resubmit the urb so we can read
+ * again.
+ */
+ case -EPROTO: /* taking inspiration from pl2303.c */
/* Continue trying to always read */
- usb_fill_bulk_urb (
- port->read_urb,
- port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- ir_read_bulk_callback,
- port);
-
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
- __func__, result);
-
- break ;
-
- default:
- dbg("%s - nonzero read bulk status received: %d",
- __func__,
- status);
+ usb_fill_bulk_urb(
+ port->read_urb,
+ port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ir_read_bulk_callback,
+ port);
+
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
break ;
-
+ default:
+ dbg("%s - nonzero read bulk status received: %d",
+ __func__, status);
+ break ;
}
-
return;
}
-static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void ir_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned char *transfer_buffer;
int result;
@@ -501,7 +512,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
dbg("%s - port %d", __func__, port->number);
- baud = tty_get_baud_rate(port->tty);
+ baud = tty_get_baud_rate(tty);
/*
* FIXME, we should compare the baud request against the
@@ -510,19 +521,36 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
*/
switch (baud) {
- case 2400: ir_baud = SPEED_2400; break;
- case 9600: ir_baud = SPEED_9600; break;
- case 19200: ir_baud = SPEED_19200; break;
- case 38400: ir_baud = SPEED_38400; break;
- case 57600: ir_baud = SPEED_57600; break;
- case 115200: ir_baud = SPEED_115200; break;
- case 576000: ir_baud = SPEED_576000; break;
- case 1152000: ir_baud = SPEED_1152000; break;
- case 4000000: ir_baud = SPEED_4000000; break;
- break;
- default:
- ir_baud = SPEED_9600;
- baud = 9600;
+ case 2400:
+ ir_baud = USB_IRDA_BR_2400;
+ break;
+ case 9600:
+ ir_baud = USB_IRDA_BR_9600;
+ break;
+ case 19200:
+ ir_baud = USB_IRDA_BR_19200;
+ break;
+ case 38400:
+ ir_baud = USB_IRDA_BR_38400;
+ break;
+ case 57600:
+ ir_baud = USB_IRDA_BR_57600;
+ break;
+ case 115200:
+ ir_baud = USB_IRDA_BR_115200;
+ break;
+ case 576000:
+ ir_baud = USB_IRDA_BR_576000;
+ break;
+ case 1152000:
+ ir_baud = USB_IRDA_BR_1152000;
+ break;
+ case 4000000:
+ ir_baud = USB_IRDA_BR_4000000;
+ break;
+ default:
+ ir_baud = USB_IRDA_BR_9600;
+ baud = 9600;
}
if (xbof == -1)
@@ -538,10 +566,11 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
transfer_buffer = port->write_urb->transfer_buffer;
*transfer_buffer = ir_xbof | ir_baud;
- usb_fill_bulk_urb (
+ usb_fill_bulk_urb(
port->write_urb,
port->serial->dev,
- usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer,
1,
ir_write_bulk_callback,
@@ -549,38 +578,44 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
port->write_urb->transfer_flags = URB_ZERO_PACKET;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, result);
/* Only speed changes are supported */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ tty_encode_baud_rate(tty, baud, baud);
}
-
-static int __init ir_init (void)
+static int __init ir_init(void)
{
int retval;
+
retval = usb_serial_register(&ir_device);
if (retval)
goto failed_usb_serial_register;
+
retval = usb_register(&ir_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
+
info(DRIVER_DESC " " DRIVER_VERSION);
+
return 0;
+
failed_usb_register:
usb_serial_deregister(&ir_device);
+
failed_usb_serial_register:
return retval;
}
-
-static void __exit ir_exit (void)
+static void __exit ir_exit(void)
{
- usb_deregister (&ir_driver);
- usb_serial_deregister (&ir_device);
+ usb_deregister(&ir_driver);
+ usb_serial_deregister(&ir_device);
}
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index a01e987c7d3..ddff37fa633 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -144,9 +144,10 @@ static void iuu_shutdown(struct usb_serial *serial)
}
}
-static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -171,8 +172,9 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
* When no card , the reader respond with TIOCM_CD
* This is known as CD autodetect mechanism
*/
-static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int rc;
@@ -316,11 +318,10 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
port->bulk_out_endpointAddress), buf,
count, &actual, HZ * 1);
- if (status != IUU_OPERATION_OK) {
+ if (status != IUU_OPERATION_OK)
dbg("%s - error = %2x", __func__, status);
- } else {
+ else
dbg("%s - write OK !", __func__);
- }
return status;
}
@@ -340,12 +341,10 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
port->bulk_in_endpointAddress), buf,
count, &actual, HZ * 1);
- if (status != IUU_OPERATION_OK) {
+ if (status != IUU_OPERATION_OK)
dbg("%s - error = %2x", __func__, status);
- } else {
+ else
dbg("%s - read OK !", __func__);
- }
-
return status;
}
@@ -630,7 +629,7 @@ static void read_buf_callback(struct urb *urb)
}
dbg("%s - %i chars to write", __func__, urb->actual_length);
- tty = port->tty;
+ tty = port->port.tty;
if (data == NULL)
dbg("%s - data is NULL !!!", __func__);
if (tty && urb->actual_length && data) {
@@ -752,11 +751,10 @@ static void iuu_uart_read_callback(struct urb *urb)
/* if nothing to write call again rxcmd */
dbg("%s - rxcmd recall", __func__);
iuu_led_activity_off(urb);
- return;
}
-static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
- int count)
+static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const u8 *buf, int count)
{
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -769,14 +767,14 @@ static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
if (priv->writelen > 0) {
/* buffer already filled but not commited */
spin_unlock_irqrestore(&priv->lock, flags);
- return (0);
+ return 0;
}
/* fill the buffer */
memcpy(priv->writebuf, buf, count);
priv->writelen = count;
spin_unlock_irqrestore(&priv->lock, flags);
- return (count);
+ return count;
}
static void read_rxcmd_callback(struct urb *urb)
@@ -948,7 +946,8 @@ static int set_control_lines(struct usb_device *dev, u8 value)
return 0;
}
-static void iuu_close(struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
/* iuu_led (port,255,0,0,0); */
struct usb_serial *serial;
@@ -964,8 +963,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
iuu_uart_off(port);
if (serial->dev) {
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
priv = usb_get_serial_port_data(port);
@@ -989,7 +988,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp)
}
}
-static int iuu_open(struct usb_serial_port *port, struct file *filp)
+static int iuu_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
u8 *buf;
@@ -1036,15 +1036,17 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
/* set the termios structure */
spin_lock_irqsave(&priv->lock, flags);
- if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
- | TIOCM_CTS | CSTOPB | PARENB;
- port->tty->termios->c_lflag = 0;
- port->tty->termios->c_oflag = 0;
- port->tty->termios->c_iflag = 0;
+ if (tty && !priv->termios_initialized) {
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ | TIOCM_CTS | CSTOPB | PARENB;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
+ tty->termios->c_lflag = 0;
+ tty->termios->c_oflag = 0;
+ tty->termios->c_iflag = 0;
priv->termios_initialized = 1;
- port->tty->low_latency = 1;
+ tty->low_latency = 1;
priv->poll = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1148,7 +1150,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- iuu_close(port, NULL);
+ iuu_close(tty, port, NULL);
return -EPROTO;
} else {
dbg("%s - rxcmd OK", __func__);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 11e439b90ea..704716f6f6d 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1,29 +1,29 @@
/*
Keyspan USB to Serial Converter driver
-
+
(C) Copyright (C) 2000-2001 Hugh Blemings <hugh@blemings.org>
(C) Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
See http://misc.nu/hugh/keyspan.html for more information.
-
+
Code in this driver inspired by and in a number of places taken
from Brian Warner's original Keyspan-PDA driver.
This driver has been put together with the support of Innosys, Inc.
and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
Thanks Guys :)
-
+
Thanks to Paulus for miscellaneous tidy ups, some largish chunks
of much nicer and/or completely new code and (perhaps most uniquely)
having the patience to sit down and explain why and where he'd changed
- stuff.
-
- Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
+ stuff.
+
+ Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
staff in their work on open source projects.
Change History
@@ -70,21 +70,21 @@
Thu May 31 11:56:42 PDT 2001 gkh
switched from using spinlock to a semaphore
-
+
(04/08/2001) gb
Identify version on module load.
-
+
(11/01/2000) Adam J. Richter
usb_device_id table support.
-
+
Tue Oct 10 23:15:33 EST 2000 Hugh
Merged Paul's changes with my USA-49W mods. Work in progress
still...
-
+
Wed Jul 19 14:00:42 EST 2000 gkh
Added module_init and module_exit functions to handle the fact that
this driver is a loadable module now.
-
+
Tue Jul 18 16:14:52 EST 2000 Hugh
Basic character input/output for USA-19 now mostly works,
fixed at 9600 baud for the moment.
@@ -107,7 +107,7 @@
#include <linux/spinlock.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "keyspan.h"
@@ -132,15 +132,15 @@ struct keyspan_serial_private {
struct urb *instat_urb;
char instat_buf[INSTAT_BUFLEN];
- /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
- /* and high-speed supported */
+ /* added to support 49wg, where data from all 4 ports comes in
+ on 1 EP and high-speed supported */
struct urb *indat_urb;
char indat_buf[INDAT49W_BUFLEN];
/* XXX this one probably will need a lock */
struct urb *glocont_urb;
char glocont_buf[GLOCONT_BUFLEN];
- char ctrl_buf[8]; // for EP0 control message
+ char ctrl_buf[8]; /* for EP0 control message */
};
struct keyspan_port_private {
@@ -186,19 +186,19 @@ struct keyspan_port_private {
int resend_cont; /* need to resend control packet */
};
-
/* Include Keyspan message headers. All current Keyspan Adapters
make use of one of five message formats which are referred
- to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
+ to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
+ within this driver. */
#include "keyspan_usa26msg.h"
#include "keyspan_usa28msg.h"
#include "keyspan_usa49msg.h"
#include "keyspan_usa90msg.h"
#include "keyspan_usa67msg.h"
-
+
/* Functions used by new usb-serial code. */
-static int __init keyspan_init (void)
+static int __init keyspan_init(void)
{
int retval;
retval = usb_serial_register(&keyspan_pre_device);
@@ -214,7 +214,7 @@ static int __init keyspan_init (void)
if (retval)
goto failed_4port_device_register;
retval = usb_register(&keyspan_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
@@ -232,35 +232,24 @@ failed_pre_device_register:
return retval;
}
-static void __exit keyspan_exit (void)
+static void __exit keyspan_exit(void)
{
- usb_deregister (&keyspan_driver);
- usb_serial_deregister (&keyspan_pre_device);
- usb_serial_deregister (&keyspan_1port_device);
- usb_serial_deregister (&keyspan_2port_device);
- usb_serial_deregister (&keyspan_4port_device);
+ usb_deregister(&keyspan_driver);
+ usb_serial_deregister(&keyspan_pre_device);
+ usb_serial_deregister(&keyspan_1port_device);
+ usb_serial_deregister(&keyspan_2port_device);
+ usb_serial_deregister(&keyspan_4port_device);
}
module_init(keyspan_init);
module_exit(keyspan_exit);
-static void keyspan_rx_throttle (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_rx_unthrottle (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
+static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
- dbg("%s", __func__);
+ dbg("%s", __func__);
p_priv = usb_get_serial_port_data(port);
@@ -273,14 +262,13 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
}
-static void keyspan_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void keyspan_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
int baud_rate, device_port;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
unsigned int cflag;
- struct tty_struct *tty = port->tty;
dbg("%s", __func__);
@@ -292,7 +280,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
/* Baud rate calculation takes baud rate as an integer
so other rates can be generated if desired. */
baud_rate = tty_get_baud_rate(tty);
- /* If no match or invalid, don't change */
+ /* If no match or invalid, don't change */
if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
/* FIXME - more to do here to ensure rate changes cleanly */
@@ -312,35 +300,32 @@ static void keyspan_set_termios (struct usb_serial_port *port,
keyspan_send_setup(port, 0);
}
-static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
unsigned int value;
- struct keyspan_port_private *p_priv;
- p_priv = usb_get_serial_port_data(port);
-
value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
((p_priv->dtr_state) ? TIOCM_DTR : 0) |
((p_priv->cts_state) ? TIOCM_CTS : 0) |
((p_priv->dsr_state) ? TIOCM_DSR : 0) |
((p_priv->dcd_state) ? TIOCM_CAR : 0) |
- ((p_priv->ri_state) ? TIOCM_RNG : 0);
+ ((p_priv->ri_state) ? TIOCM_RNG : 0);
return value;
}
-static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct keyspan_port_private *p_priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
- p_priv = usb_get_serial_port_data(port);
-
if (set & TIOCM_RTS)
p_priv->rts_state = 1;
if (set & TIOCM_DTR)
p_priv->dtr_state = 1;
-
if (clear & TIOCM_RTS)
p_priv->rts_state = 0;
if (clear & TIOCM_DTR)
@@ -349,35 +334,29 @@ static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
return 0;
}
-static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
-
- /* Write function is similar for the four protocols used
- with only a minor change for usa90 (usa19hs) required */
-static int keyspan_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+/* Write function is similar for the four protocols used
+ with only a minor change for usa90 (usa19hs) required */
+static int keyspan_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
int flip;
int left, todo;
struct urb *this_urb;
- int err, maxDataLen, dataOffset;
+ int err, maxDataLen, dataOffset;
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
if (d_details->msg_format == msg_usa90) {
- maxDataLen = 64;
+ maxDataLen = 64;
dataOffset = 0;
} else {
maxDataLen = 63;
dataOffset = 1;
}
-
+
dbg("%s - for port %d (%d chars), flip=%d",
__func__, port->number, count, p_priv->out_flip);
@@ -387,37 +366,40 @@ static int keyspan_write(struct usb_serial_port *port,
todo = maxDataLen;
flip = p_priv->out_flip;
-
+
/* Check we have a valid urb/endpoint before we use it... */
- if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb == NULL) {
/* no bulk out, so return 0 bytes written */
dbg("%s - no output urb :(", __func__);
return count;
}
- dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
+ dbg("%s - endpoint %d flip %d",
+ __func__, usb_pipeendpoint(this_urb->pipe), flip);
if (this_urb->status == -EINPROGRESS) {
- if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
+ if (time_before(jiffies,
+ p_priv->tx_start_time[flip] + 10 * HZ))
break;
usb_unlink_urb(this_urb);
break;
}
- /* First byte in buffer is "last flag" (except for usa19hx) - unused so
- for now so set to zero */
+ /* First byte in buffer is "last flag" (except for usa19hx)
+ - unused so for now so set to zero */
((char *)this_urb->transfer_buffer)[0] = 0;
- memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
+ memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
buf += todo;
/* send the data out the bulk port */
this_urb->transfer_buffer_length = todo + dataOffset;
this_urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("usb_submit_urb(write bulk) failed (%d)", err);
- }
p_priv->tx_start_time[flip] = jiffies;
/* Flip for next time if usa26 or usa28 interface
@@ -437,7 +419,7 @@ static void usa26_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -448,17 +430,18 @@ static void usa26_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
- /* no errors on individual bytes, only possible overrun err*/
+ /* no errors on individual bytes, only
+ possible overrun err */
if (data[0] & RXERROR_OVERRUN)
- err = TTY_OVERRUN;
- else err = 0;
- for (i = 1; i < urb->actual_length ; ++i) {
+ err = TTY_OVERRUN;
+ else
+ err = 0;
+ for (i = 1; i < urb->actual_length ; ++i)
tty_insert_flip_char(tty, data[i], err);
- }
} else {
/* some bytes had errors, every byte has status */
dbg("%s - RX error!!!!", __func__);
@@ -476,17 +459,19 @@ static void usa26_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
-
- /* Resubmit urb so we continue receiving */
+
+ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
return;
}
- /* Outdat handling is common for all devices */
+/* Outdat handling is common for all devices */
static void usa2x_outdat_callback(struct urb *urb)
{
struct usb_serial_port *port;
@@ -494,16 +479,16 @@ static void usa2x_outdat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+ dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
- if (port->open_count)
+ if (port->port.count)
usb_serial_port_softint(port);
}
static void usa26_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
-
+ dbg("%s", __func__);
+
}
static void usa26_outcont_callback(struct urb *urb)
@@ -515,8 +500,9 @@ static void usa26_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa26_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -552,14 +538,14 @@ static void usa26_instat_callback(struct urb *urb)
/* Now do something useful with the data */
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
@@ -567,39 +553,38 @@ static void usa26_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa26_glocont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
-
+ dbg("%s", __func__);
}
static void usa28_indat_callback(struct urb *urb)
{
- int i, err;
+ int err;
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data;
struct keyspan_port_private *p_priv;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
port = urb->context;
p_priv = usb_get_serial_port_data(port);
@@ -619,20 +604,20 @@ static void usa28_indat_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
p_priv->in_flip ^= 1;
urb = p_priv->in_urbs[p_priv->in_flip];
@@ -641,7 +626,7 @@ static void usa28_indat_callback(struct urb *urb)
static void usa28_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa28_outcont_callback(struct urb *urb)
@@ -653,8 +638,9 @@ static void usa28_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa28_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -684,19 +670,18 @@ static void usa28_instat_callback(struct urb *urb)
/*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10], data[11]);*/
-
- /* Now do something useful with the data */
- msg = (struct keyspan_usa28_portStatusMessage *)data;
+ /* Now do something useful with the data */
+ msg = (struct keyspan_usa28_portStatusMessage *)data;
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
goto exit;
}
port = serial->port[msg->port];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -704,25 +689,25 @@ static void usa28_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa28_glocont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
@@ -733,7 +718,7 @@ static void usa49_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
@@ -741,8 +726,9 @@ static void usa49_glocont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa49_send_setup(serial, port,
+ p_priv->resend_cont - 1);
break;
}
}
@@ -761,7 +747,7 @@ static void usa49_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -770,7 +756,8 @@ static void usa49_instat_callback(struct urb *urb)
return;
}
- if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+ if (urb->actual_length !=
+ sizeof(struct keyspan_usa49_portStatusMessage)) {
dbg("%s - bad length %d", __func__, urb->actual_length);
goto exit;
}
@@ -778,18 +765,19 @@ static void usa49_instat_callback(struct urb *urb)
/*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
data[0], data[1], data[2], data[3], data[4], data[5],
data[6], data[7], data[8], data[9], data[10]);*/
-
- /* Now do something useful with the data */
+
+ /* Now do something useful with the data */
msg = (struct keyspan_usa49_portStatusMessage *)data;
- /* Check port number from message and retrieve private data */
+ /* Check port number from message and retrieve private data */
if (msg->portNumber >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
+ dbg("%s - Unexpected port number %d",
+ __func__, msg->portNumber);
goto exit;
}
port = serial->port[msg->portNumber];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -797,26 +785,26 @@ static void usa49_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
- /* Resubmit urb so we continue receiving */
+ /* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit: ;
}
static void usa49_inack_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa49_indat_callback(struct urb *urb)
@@ -828,7 +816,7 @@ static void usa49_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -839,14 +827,13 @@ static void usa49_indat_callback(struct urb *urb)
}
port = urb->context;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
/* no error on any byte */
- for (i = 1; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data + 1,
+ urb->actual_length - 1);
} else {
/* some bytes had errors, every byte has status */
for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -863,13 +850,15 @@ static void usa49_indat_callback(struct urb *urb)
}
tty_flip_buffer_push(tty);
}
-
- /* Resubmit urb so we continue receiving */
+
+ /* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
}
static void usa49wg_indat_callback(struct urb *urb)
@@ -881,7 +870,7 @@ static void usa49wg_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -899,12 +888,12 @@ static void usa49wg_indat_callback(struct urb *urb)
/* Check port number from message*/
if (data[i] >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d",
+ dbg("%s - Unexpected port number %d",
__func__, data[i]);
return;
}
port = serial->port[data[i++]];
- tty = port->tty;
+ tty = port->port.tty;
len = data[i++];
/* 0x80 bit is error flag */
@@ -912,7 +901,7 @@ static void usa49wg_indat_callback(struct urb *urb)
/* no error on any byte */
i++;
for (x = 1; x < len ; ++x)
- if (port->open_count)
+ if (port->port.count)
tty_insert_flip_char(tty,
data[i++], 0);
else
@@ -930,13 +919,13 @@ static void usa49wg_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- if (port->open_count)
+ if (port->port.count)
tty_insert_flip_char(tty,
data[i+1], flag);
i += 2;
}
}
- if (port->open_count)
+ if (port->port.count)
tty_flip_buffer_push(tty);
}
}
@@ -952,7 +941,7 @@ static void usa49wg_indat_callback(struct urb *urb)
/* not used, usa-49 doesn't have per-port control endpoints */
static void usa49_outcont_callback(struct urb *urb)
{
- dbg ("%s", __func__);
+ dbg("%s", __func__);
}
static void usa90_indat_callback(struct urb *urb)
@@ -965,7 +954,7 @@ static void usa90_indat_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
endpoint = usb_pipeendpoint(urb->pipe);
@@ -978,29 +967,26 @@ static void usa90_indat_callback(struct urb *urb)
port = urb->context;
p_priv = usb_get_serial_port_data(port);
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
-
/* if current mode is DMA, looks like usa28 format
- otherwise looks like usa26 data format */
+ otherwise looks like usa26 data format */
- if (p_priv->baud > 57600) {
- for (i = 0; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i], 0);
- }
+ if (p_priv->baud > 57600)
+ tty_insert_flip_string(tty, data, urb->actual_length);
else {
-
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
- /* no errors on individual bytes, only possible overrun err*/
+ /* no errors on individual bytes, only
+ possible overrun err*/
if (data[0] & RXERROR_OVERRUN)
- err = TTY_OVERRUN;
- else err = 0;
- for (i = 1; i < urb->actual_length ; ++i)
- tty_insert_flip_char(tty, data[i], err);
-
- }
- else {
+ err = TTY_OVERRUN;
+ else
+ err = 0;
+ for (i = 1; i < urb->actual_length ; ++i)
+ tty_insert_flip_char(tty, data[i],
+ err);
+ } else {
/* some bytes had errors, every byte has status */
dbg("%s - RX error!!!!", __func__);
for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -1012,19 +998,22 @@ static void usa90_indat_callback(struct urb *urb)
if (stat & RXERROR_PARITY)
flag |= TTY_PARITY;
/* XXX should handle break (0x10) */
- tty_insert_flip_char(tty, data[i+1], flag);
+ tty_insert_flip_char(tty, data[i+1],
+ flag);
}
}
}
tty_flip_buffer_push(tty);
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if (port->open_count)
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
- dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
+ if (port->port.count) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)",
+ __func__, err);
+ }
return;
}
@@ -1056,7 +1045,7 @@ static void usa90_instat_callback(struct urb *urb)
port = serial->port[0];
p_priv = usb_get_serial_port_data(port);
-
+
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -1064,19 +1053,19 @@ static void usa90_instat_callback(struct urb *urb)
p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
p_priv->ri_state = ((msg->ri) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
-
+
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - resubmit read urb failed. (%d)", __func__, err);
- }
exit:
;
}
@@ -1090,8 +1079,9 @@ static void usa90_outcont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
- keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+ dbg("%s - sending setup", __func__);
+ keyspan_usa90_send_setup(port->serial, port,
+ p_priv->resend_cont - 1);
}
}
@@ -1107,7 +1097,7 @@ static void usa67_instat_callback(struct urb *urb)
int old_dcd_state;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
@@ -1116,7 +1106,8 @@ static void usa67_instat_callback(struct urb *urb)
return;
}
- if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+ if (urb->actual_length !=
+ sizeof(struct keyspan_usa67_portStatusMessage)) {
dbg("%s - bad length %d", __func__, urb->actual_length);
return;
}
@@ -1127,7 +1118,7 @@ static void usa67_instat_callback(struct urb *urb)
/* Check port number from message and retrieve private data */
if (msg->port >= serial->num_ports) {
- dbg ("%s - Unexpected port number %d", __func__, msg->port);
+ dbg("%s - Unexpected port number %d", __func__, msg->port);
return;
}
@@ -1139,10 +1130,10 @@ static void usa67_instat_callback(struct urb *urb)
p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty)
+ if (port->port.tty && !C_CLOCAL(port->port.tty)
&& old_dcd_state != p_priv->dcd_state) {
if (old_dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
/* else */
/* wake_up_interruptible(&p_priv->open_wait); */
}
@@ -1161,7 +1152,7 @@ static void usa67_glocont_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
int i;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
serial = urb->context;
for (i = 0; i < serial->num_ports; ++i) {
@@ -1169,7 +1160,7 @@ static void usa67_glocont_callback(struct urb *urb)
p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
- dbg ("%s - sending setup", __func__);
+ dbg("%s - sending setup", __func__);
keyspan_usa67_send_setup(serial, port,
p_priv->resend_cont - 1);
break;
@@ -1177,8 +1168,9 @@ static void usa67_glocont_callback(struct urb *urb)
}
}
-static int keyspan_write_room (struct usb_serial_port *port)
+static int keyspan_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
int flip;
@@ -1191,32 +1183,30 @@ static int keyspan_write_room (struct usb_serial_port *port)
/* FIXME: locking */
if (d_details->msg_format == msg_usa90)
- data_len = 64;
+ data_len = 64;
else
data_len = 63;
flip = p_priv->out_flip;
/* Check both endpoints to see if any are available. */
- if ((this_urb = p_priv->out_urbs[flip]) != NULL) {
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb != NULL) {
if (this_urb->status != -EINPROGRESS)
- return (data_len);
- flip = (flip + 1) & d_details->outdat_endp_flip;
- if ((this_urb = p_priv->out_urbs[flip]) != NULL)
+ return data_len;
+ flip = (flip + 1) & d_details->outdat_endp_flip;
+ this_urb = p_priv->out_urbs[flip];
+ if (this_urb != NULL) {
if (this_urb->status != -EINPROGRESS)
- return (data_len);
+ return data_len;
+ }
}
return 0;
}
-static int keyspan_chars_in_buffer (struct usb_serial_port *port)
-{
- return 0;
-}
-
-
-static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct keyspan_port_private *p_priv;
struct keyspan_serial_private *s_priv;
@@ -1225,7 +1215,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
int i, err;
int baud_rate, device_port;
struct urb *urb;
- unsigned int cflag;
+ unsigned int cflag = 0;
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -1247,50 +1237,53 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < 2; i++) {
- if ((urb = p_priv->in_urbs[i]) == NULL)
+ urb = p_priv->in_urbs[i];
+ if (urb == NULL)
continue;
urb->dev = serial->dev;
- /* make sure endpoint data toggle is synchronized with the device */
-
+ /* make sure endpoint data toggle is synchronized
+ with the device */
usb_clear_halt(urb->dev, urb->pipe);
-
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
- dbg("%s - submit urb %d failed (%d)", __func__, i, err);
- }
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err != 0)
+ dbg("%s - submit urb %d failed (%d)",
+ __func__, i, err);
}
/* Reset low level data toggle on out endpoints */
for (i = 0; i < 2; i++) {
- if ((urb = p_priv->out_urbs[i]) == NULL)
+ urb = p_priv->out_urbs[i];
+ if (urb == NULL)
continue;
urb->dev = serial->dev;
- /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), 0); */
}
/* get the terminal config for the setup message now so we don't
* need to send 2 of them */
- cflag = port->tty->termios->c_cflag;
device_port = port->number - port->serial->minor;
-
- /* Baud rate calculation takes baud rate as an integer
- so other rates can be generated if desired. */
- baud_rate = tty_get_baud_rate(port->tty);
- /* If no match or invalid, leave as default */
- if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
- NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
- p_priv->baud = baud_rate;
+ if (tty) {
+ cflag = tty->termios->c_cflag;
+ /* Baud rate calculation takes baud rate as an integer
+ so other rates can be generated if desired. */
+ baud_rate = tty_get_baud_rate(tty);
+ /* If no match or invalid, leave as default */
+ if (baud_rate >= 0
+ && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+ NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
+ p_priv->baud = baud_rate;
+ }
}
-
/* set CTS/RTS handshake etc. */
p_priv->cflag = cflag;
p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
keyspan_send_setup(port, 1);
- //mdelay(100);
- //keyspan_set_termios(port, NULL);
+ /* mdelay(100); */
+ /* keyspan_set_termios(port, NULL); */
return 0;
}
@@ -1301,7 +1294,8 @@ static inline void stop_urb(struct urb *urb)
usb_kill_urb(urb);
}
-static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -1311,15 +1305,15 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
-
+
p_priv->rts_state = 0;
p_priv->dtr_state = 0;
-
+
if (serial->dev) {
keyspan_send_setup(port, 2);
/* pilot-xfer seems to work best with this delay */
mdelay(100);
- // keyspan_set_termios(port, NULL);
+ /* keyspan_set_termios(port, NULL); */
}
/*while (p_priv->outcont_urb->status == -EINPROGRESS) {
@@ -1338,11 +1332,11 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
stop_urb(p_priv->out_urbs[i]);
}
}
- port->tty = NULL;
+ port->port.tty = NULL;
}
- /* download the firmware to a pre-renumeration device */
-static int keyspan_fake_startup (struct usb_serial *serial)
+/* download the firmware to a pre-renumeration device */
+static int keyspan_fake_startup(struct usb_serial *serial)
{
int response;
const struct ihex_binrec *record;
@@ -1352,10 +1346,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
dbg("Keyspan startup version %04x product %04x",
le16_to_cpu(serial->dev->descriptor.bcdDevice),
le16_to_cpu(serial->dev->descriptor.idProduct));
-
- if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
+
+ if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
+ != 0x8000) {
dbg("Firmware already loaded. Quitting.");
- return(1);
+ return 1;
}
/* Select firmware image on the basis of idProduct */
@@ -1379,11 +1374,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
case keyspan_usa19_pre_product_id:
fw_name = "keyspan/usa19.fw";
break;
-
+
case keyspan_usa19qi_pre_product_id:
fw_name = "keyspan/usa19qi.fw";
break;
-
+
case keyspan_mpr_pre_product_id:
fw_name = "keyspan/mpr.fw";
break;
@@ -1391,15 +1386,15 @@ static int keyspan_fake_startup (struct usb_serial *serial)
case keyspan_usa19qw_pre_product_id:
fw_name = "keyspan/usa19qw.fw";
break;
-
+
case keyspan_usa18x_pre_product_id:
fw_name = "keyspan/usa18x.fw";
break;
-
+
case keyspan_usa19w_pre_product_id:
fw_name = "keyspan/usa19w.fw";
break;
-
+
case keyspan_usa49w_pre_product_id:
fw_name = "keyspan/usa49w.fw";
break;
@@ -1431,8 +1426,7 @@ static int keyspan_fake_startup (struct usb_serial *serial)
(unsigned char *)record->data,
be16_to_cpu(record->len), 0xa0);
if (response < 0) {
- dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
- "firmware (%d %04X %p %d)\n",
+ dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
response, be32_to_cpu(record->addr),
record->data, be16_to_cpu(record->len));
break;
@@ -1445,7 +1439,7 @@ static int keyspan_fake_startup (struct usb_serial *serial)
response = ezusb_set_reset(serial, 0);
/* we don't want this device to have a driver assigned to it. */
- return (1);
+ return 1;
}
/* Helper functions used by keyspan_setup_urbs */
@@ -1467,7 +1461,7 @@ static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *se
return NULL;
}
-static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
+static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback)(struct urb *))
{
@@ -1478,10 +1472,10 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
if (endpoint == -1)
return NULL; /* endpoint not needed */
- dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
+ dbg("%s - alloc for endpoint %d.", __func__, endpoint);
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
- dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
+ dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
return NULL;
}
@@ -1554,7 +1548,7 @@ static struct callbacks {
}, {
/* msg_usa90 callbacks */
.instat_callback = usa90_instat_callback,
- .glocont_callback = usa28_glocont_callback,
+ .glocont_callback = usa28_glocont_callback,
.indat_callback = usa90_indat_callback,
.outdat_callback = usa2x_outdat_callback,
.inack_callback = usa28_inack_callback,
@@ -1582,16 +1576,16 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
struct callbacks *cback;
int endp;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
- /* Setup values for the various callback routines */
+ /* Setup values for the various callback routines */
cback = &keyspan_callbacks[d_details->msg_format];
- /* Allocate and set up urbs for each one that is in use,
- starting with instat endpoints */
+ /* Allocate and set up urbs for each one that is in use,
+ starting with instat endpoints */
s_priv->instat_urb = keyspan_setup_urb
(serial, d_details->instat_endpoint, USB_DIR_IN,
serial, s_priv->instat_buf, INSTAT_BUFLEN,
@@ -1607,8 +1601,8 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
cback->glocont_callback);
- /* Setup endpoints for each port specific thing */
- for (i = 0; i < d_details->num_ports; i ++) {
+ /* Setup endpoints for each port specific thing */
+ for (i = 0; i < d_details->num_ports; i++) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
@@ -1644,8 +1638,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
port, p_priv->outcont_buffer, 64,
cback->outcont_callback);
- }
-
+ }
}
/* usa19 function doesn't require prescaler */
@@ -1653,46 +1646,39 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div, /* divisor */
+ div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
-
- dbg ("%s - %d.", __func__, baud_rate);
-
- /* prevent divide by zero... */
- if( (b16 = (baud_rate * 16L)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- /* Any "standard" rate over 57k6 is marginal on the USA-19
- as we run out of divisor resolution. */
- if (baud_rate > 57600) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
-
- /* calculate the divisor and the counter (its inverse) */
- if( (div = (baudclk / b16)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
+ dbg("%s - %d.", __func__, baud_rate);
+
+ /* prevent divide by zero... */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ /* Any "standard" rate over 57k6 is marginal on the USA-19
+ as we run out of divisor resolution. */
+ if (baud_rate > 57600)
+ return KEYSPAN_INVALID_BAUD_RATE;
+
+ /* calculate the divisor and the counter (its inverse) */
+ div = baudclk / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ else
cnt = 0 - div;
- }
- if(div > 0xffff) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* return the counter values if non-null */
- if (rate_low) {
+ /* return the counter values if non-null */
+ if (rate_low)
*rate_low = (u8) (cnt & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
- }
- if (rate_low && rate_hi) {
- dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
- }
-
- return (KEYSPAN_BAUD_RATE_OK);
+ if (rate_low && rate_hi)
+ dbg("%s - %d %02x %02x.",
+ __func__, baud_rate, *rate_hi, *rate_low);
+ return KEYSPAN_BAUD_RATE_OK;
}
/* usa19hs function doesn't require prescaler */
@@ -1700,34 +1686,35 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div; /* divisor */
-
- dbg ("%s - %d.", __func__, baud_rate);
+ div; /* divisor */
- /* prevent divide by zero... */
- if( (b16 = (baud_rate * 16L)) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
-
+ dbg("%s - %d.", __func__, baud_rate);
+ /* prevent divide by zero... */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* calculate the divisor */
- if( (div = (baudclk / b16)) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
+ /* calculate the divisor */
+ div = baudclk / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- if(div > 0xffff)
- return (KEYSPAN_INVALID_BAUD_RATE);
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* return the counter values if non-null */
- if (rate_low)
+ /* return the counter values if non-null */
+ if (rate_low)
*rate_low = (u8) (div & 0xff);
-
- if (rate_hi)
+
+ if (rate_hi)
*rate_hi = (u8) ((div >> 8) & 0xff);
-
- if (rate_low && rate_hi)
- dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
-
- return (KEYSPAN_BAUD_RATE_OK);
+
+ if (rate_low && rate_hi)
+ dbg("%s - %d %02x %02x.",
+ __func__, baud_rate, *rate_hi, *rate_low);
+
+ return KEYSPAN_BAUD_RATE_OK;
}
static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
@@ -1735,64 +1722,61 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
clk, /* clock with 13/8 prescaler */
- div, /* divisor using 13/8 prescaler */
+ div, /* divisor using 13/8 prescaler */
res, /* resulting baud rate using 13/8 prescaler */
diff, /* error using 13/8 prescaler */
smallest_diff;
u8 best_prescaler;
int i;
- dbg ("%s - %d.", __func__, baud_rate);
+ dbg("%s - %d.", __func__, baud_rate);
- /* prevent divide by zero */
- if( (b16 = baud_rate * 16L) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ /* prevent divide by zero */
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
- /* Calculate prescaler by trying them all and looking
- for best fit */
-
- /* start with largest possible difference */
+ /* Calculate prescaler by trying them all and looking
+ for best fit */
+
+ /* start with largest possible difference */
smallest_diff = 0xffffffff;
/* 0 is an invalid prescaler, used as a flag */
best_prescaler = 0;
- for(i = 8; i <= 0xff; ++i) {
+ for (i = 8; i <= 0xff; ++i) {
clk = (baudclk * 8) / (u32) i;
-
- if( (div = clk / b16) == 0) {
+
+ div = clk / b16;
+ if (div == 0)
continue;
- }
res = clk / div;
- diff= (res > b16) ? (res-b16) : (b16-res);
+ diff = (res > b16) ? (res-b16) : (b16-res);
- if(diff < smallest_diff) {
+ if (diff < smallest_diff) {
best_prescaler = i;
smallest_diff = diff;
}
}
- if(best_prescaler == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ if (best_prescaler == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
clk = (baudclk * 8) / (u32) best_prescaler;
div = clk / b16;
- /* return the divisor and prescaler if non-null */
- if (rate_low) {
+ /* return the divisor and prescaler if non-null */
+ if (rate_low)
*rate_low = (u8) (div & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((div >> 8) & 0xff);
- }
if (prescaler) {
*prescaler = best_prescaler;
/* dbg("%s - %d %d", __func__, *prescaler, div); */
}
- return (KEYSPAN_BAUD_RATE_OK);
+ return KEYSPAN_BAUD_RATE_OK;
}
/* USA-28 supports different maximum baud rates on each port */
@@ -1800,57 +1784,51 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
u8 *rate_low, u8 *prescaler, int portnum)
{
u32 b16, /* baud rate times 16 (actual rate used internally) */
- div, /* divisor */
+ div, /* divisor */
cnt; /* inverse of divisor (programmed into 8051) */
- dbg ("%s - %d.", __func__, baud_rate);
+ dbg("%s - %d.", __func__, baud_rate);
/* prevent divide by zero */
- if ((b16 = baud_rate * 16L) == 0)
- return (KEYSPAN_INVALID_BAUD_RATE);
-
- /* calculate the divisor and the counter (its inverse) */
- if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
+ b16 = baud_rate * 16L;
+ if (b16 == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+
+ /* calculate the divisor and the counter (its inverse) */
+ div = KEYSPAN_USA28_BAUDCLK / b16;
+ if (div == 0)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ else
cnt = 0 - div;
- }
- /* check for out of range, based on portnum,
- and return result */
- if(portnum == 0) {
- if(div > 0xffff)
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- else {
- if(portnum == 1) {
- if(div > 0xff) {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
- }
- else {
- return (KEYSPAN_INVALID_BAUD_RATE);
- }
+ /* check for out of range, based on portnum,
+ and return result */
+ if (portnum == 0) {
+ if (div > 0xffff)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ } else {
+ if (portnum == 1) {
+ if (div > 0xff)
+ return KEYSPAN_INVALID_BAUD_RATE;
+ } else
+ return KEYSPAN_INVALID_BAUD_RATE;
}
/* return the counter values if not NULL
(port 1 will ignore retHi) */
- if (rate_low) {
+ if (rate_low)
*rate_low = (u8) (cnt & 0xff);
- }
- if (rate_hi) {
+ if (rate_hi)
*rate_hi = (u8) ((cnt >> 8) & 0xff);
- }
- dbg ("%s - %d OK.", __func__, baud_rate);
- return (KEYSPAN_BAUD_RATE_OK);
+ dbg("%s - %d OK.", __func__, baud_rate);
+ return KEYSPAN_BAUD_RATE_OK;
}
static int keyspan_usa26_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa26_portControlMessage msg;
+ struct keyspan_usa26_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
@@ -1858,7 +1836,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int device_port, err;
- dbg ("%s reset=%d", __func__, reset_port);
+ dbg("%s reset=%d", __func__, reset_port);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -1881,22 +1859,22 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
-
- /* Only set baud rate if it's changed */
+ memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
+
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -1922,7 +1900,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -1963,7 +1941,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -1975,23 +1953,23 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
msg.resetDataToggle = 0x0;
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setTxTriState_setRts = 0xff;
msg.txTriState_rts = p_priv->rts_state;
msg.setHskoa_setDtr = 0xff;
msg.hskoa_dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
#if 0
else {
dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
@@ -2007,14 +1985,14 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa28_portControlMessage msg;
+ struct keyspan_usa28_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
struct urb *this_urb;
int device_port, err;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2022,7 +2000,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
device_port = port->number - port->serial->minor;
/* only do something if we have a bulk out endpoint */
- if ((this_urb = p_priv->outcont_urb) == NULL) {
+ this_urb = p_priv->outcont_urb;
+ if (this_urb == NULL) {
dbg("%s - oops no urb.", __func__);
return -1;
}
@@ -2032,17 +2011,18 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg ("%s already writing", __func__);
+ dbg("%s already writing", __func__);
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
msg.setBaudRate = 1;
if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
- &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
+ &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate requested %d.",
+ __func__, p_priv->baud);
msg.baudLo = 0xff;
msg.baudHi = 0xb2; /* Values for 9600 baud */
}
@@ -2053,7 +2033,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
msg.xonFlowControl = 0;
- /* Do handshaking outputs, DTR is inverted relative to RTS */
+ /* Do handshaking outputs, DTR is inverted relative to RTS */
msg.rts = p_priv->rts_state;
msg.dtr = p_priv->dtr_state;
@@ -2095,7 +2075,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
}
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txForceXoff = 0;
@@ -2109,15 +2089,15 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
}
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed", __func__);
- }
#if 0
else {
dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
@@ -2140,7 +2120,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2151,7 +2131,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
/* Work out which port within the device is being setup */
device_port = port->number - port->serial->minor;
- dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
+ dbg("%s - endpoint %d port %d (%d)",
+ __func__, usb_pipeendpoint(this_urb->pipe),
+ port->number, device_port);
/* Make sure we have an urb then send the message */
if (this_urb == NULL) {
@@ -2165,30 +2147,30 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
/*msg.portNumber = port->number;*/
msg.portNumber = device_port;
-
- /* Only set baud rate if it's changed */
+
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
}
- //msg.setPrescaler = 0xff;
+ /* msg.setPrescaler = 0xff; */
}
msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
@@ -2209,19 +2191,19 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
msg.xonFlowControl = 0;
msg.setFlowControl = 0xff;
-
+
msg.forwardingLength = 16;
msg.xonChar = 17;
msg.xoffChar = 19;
- /* Opening port */
+ /* Opening port */
if (reset_port == 1) {
msg._txOn = 1;
msg._txOff = 0;
@@ -2253,7 +2235,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
}
/* Sending intermediate configs */
else {
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -2267,16 +2249,17 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
msg.disablePort = 0;
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setRts = 0xff;
msg.rts = p_priv->rts_state;
msg.setDtr = 0xff;
msg.dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- /* if the device is a 49wg, we send control message on usb control EP 0 */
+ /* if the device is a 49wg, we send control message on usb
+ control EP 0 */
if (d_details->product_id == keyspan_usa49wg_product_id) {
dr = (void *)(s_priv->ctrl_buf);
@@ -2286,23 +2269,24 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
dr->wIndex = 0;
dr->wLength = cpu_to_le16(sizeof(msg));
- memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+ memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
- usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
- usa49_glocont_callback, serial);
+ usb_fill_control_urb(this_urb, serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ (unsigned char *)dr, s_priv->glocont_buf,
+ sizeof(msg), usa49_glocont_callback, serial);
} else {
memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
-
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
}
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
#if 0
else {
dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
@@ -2318,7 +2302,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa90_portControlMessage msg;
+ struct keyspan_usa90_portControlMessage msg;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
@@ -2326,14 +2310,15 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
int err;
u8 prescaler;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
/* only do something if we have a bulk out endpoint */
- if ((this_urb = p_priv->outcont_urb) == NULL) {
+ this_urb = p_priv->outcont_urb;
+ if (this_urb == NULL) {
dbg("%s - oops no urb.", __func__);
return -1;
}
@@ -2343,24 +2328,24 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- dbg ("%s already writing", __func__);
+ dbg("%s already writing", __func__);
mdelay(5);
- return(-1);
+ return -1;
}
- memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
+ memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
- /* Only set baud rate if it's changed */
+ /* Only set baud rate if it's changed */
if (p_priv->old_baud != p_priv->baud) {
p_priv->old_baud = p_priv->baud;
msg.setClocking = 0x01;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
p_priv->baud = 9600;
- d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
+ d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
&msg.baudHi, &msg.baudLo, &prescaler, 0);
}
msg.setRxMode = 1;
@@ -2368,13 +2353,10 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
}
/* modes must always be correctly specified */
- if (p_priv->baud > 57600)
- {
+ if (p_priv->baud > 57600) {
msg.rxMode = RXMODE_DMA;
msg.txMode = TXMODE_DMA;
- }
- else
- {
+ } else {
msg.rxMode = RXMODE_BYHAND;
msg.txMode = TXMODE_BYHAND;
}
@@ -2397,7 +2379,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
if (p_priv->old_cflag != p_priv->cflag) {
p_priv->old_cflag = p_priv->cflag;
@@ -2408,47 +2390,46 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
msg.txFlowControl = TXFLOW_CTS;
msg.setTxFlowControl = 0x01;
msg.setRxFlowControl = 0x01;
-
+
msg.rxForwardingLength = 16;
- msg.rxForwardingTimeout = 16;
+ msg.rxForwardingTimeout = 16;
msg.txAckSetting = 0;
msg.xonChar = 17;
msg.xoffChar = 19;
- /* Opening port */
+ /* Opening port */
if (reset_port == 1) {
msg.portEnabled = 1;
msg.rxFlush = 1;
msg.txBreak = (p_priv->break_on);
}
/* Closing port */
- else if (reset_port == 2) {
+ else if (reset_port == 2)
msg.portEnabled = 0;
- }
/* Sending intermediate configs */
else {
- if (port->open_count)
+ if (port->port.count)
msg.portEnabled = 1;
msg.txBreak = (p_priv->break_on);
}
- /* Do handshaking outputs */
+ /* Do handshaking outputs */
msg.setRts = 0x01;
msg.rts = p_priv->rts_state;
msg.setDtr = 0x01;
msg.dtr = p_priv->dtr_state;
-
+
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
/* send the data out the device on control endpoint */
this_urb->transfer_buffer_length = sizeof(msg);
this_urb->dev = serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
- }
return 0;
}
@@ -2463,7 +2444,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
struct urb *this_urb;
int err, device_port;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
@@ -2486,9 +2467,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
- /* dbg ("%s - already writing", __func__); */
+ /* dbg("%s - already writing", __func__); */
mdelay(5);
- return(-1);
+ return -1;
}
memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
@@ -2501,9 +2482,9 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
msg.setClocking = 0xff;
if (d_details->calculate_baud_rate
(p_priv->baud, d_details->baudclk, &msg.baudHi,
- &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
- dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
- p_priv->baud);
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.",
+ __func__, p_priv->baud);
msg.baudLo = 0;
msg.baudHi = 125; /* Values for 9600 baud */
msg.prescaler = 10;
@@ -2529,7 +2510,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
if (p_priv->cflag & PARENB) {
/* note USA_PARITY_NONE == 0 */
msg.lcr |= (p_priv->cflag & PARODD)?
- USA_PARITY_ODD: USA_PARITY_EVEN;
+ USA_PARITY_ODD : USA_PARITY_EVEN;
}
msg.setLcr = 0xff;
@@ -2566,7 +2547,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
msg.resetDataToggle = 0;
} else {
/* Sending intermediate configs */
- msg._txOn = (! p_priv->break_on);
+ msg._txOn = (!p_priv->break_on);
msg._txOff = 0;
msg.txFlush = 0;
msg.txBreak = (p_priv->break_on);
@@ -2606,7 +2587,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -2633,7 +2614,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
/* Gets called by the "real" driver (ie once firmware is loaded
and renumeration has taken place. */
-static int keyspan_startup (struct usb_serial *serial)
+static int keyspan_startup(struct usb_serial *serial)
{
int i, err;
struct usb_serial_port *port;
@@ -2644,17 +2625,20 @@ static int keyspan_startup (struct usb_serial *serial)
dbg("%s", __func__);
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
- if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+ if (d_details->product_id ==
+ le16_to_cpu(serial->dev->descriptor.idProduct))
break;
if (d_details == NULL) {
- dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
+ dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
+ __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
return 1;
}
/* Setup private data for serial driver */
s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
if (!s_priv) {
- dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
+ dbg("%s - kmalloc for keyspan_serial_private failed.",
+ __func__);
return -ENOMEM;
}
@@ -2664,10 +2648,11 @@ static int keyspan_startup (struct usb_serial *serial)
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ p_priv = kzalloc(sizeof(struct keyspan_port_private),
+ GFP_KERNEL);
if (!p_priv) {
dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
- return (1);
+ return 1;
}
p_priv->device_details = d_details;
usb_set_serial_port_data(port, p_priv);
@@ -2689,11 +2674,11 @@ static int keyspan_startup (struct usb_serial *serial)
dbg("%s - submit indat urb failed %d", __func__,
err);
}
-
+
return 0;
}
-static void keyspan_shutdown (struct usb_serial *serial)
+static void keyspan_shutdown(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
@@ -2745,8 +2730,8 @@ static void keyspan_shutdown (struct usb_serial *serial)
}
}
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("keyspan/usa28.fw");
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index b52fb657a24..38b4582e073 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -35,17 +35,18 @@
/* Function prototypes for Keyspan serial converter */
-static int keyspan_open (struct usb_serial_port *port,
+static int keyspan_open (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct file *filp);
-static void keyspan_close (struct usb_serial_port *port,
+static void keyspan_close (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct file *filp);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_shutdown (struct usb_serial *serial);
-static void keyspan_rx_throttle (struct usb_serial_port *port);
-static void keyspan_rx_unthrottle (struct usb_serial_port *port);
-static int keyspan_write_room (struct usb_serial_port *port);
+static int keyspan_write_room (struct tty_struct *tty);
-static int keyspan_write (struct usb_serial_port *port,
+static int keyspan_write (struct tty_struct *tty,
+ struct usb_serial_port *port,
const unsigned char *buf,
int count);
@@ -53,18 +54,14 @@ static void keyspan_send_setup (struct usb_serial_port *port,
int reset_port);
-static int keyspan_chars_in_buffer (struct usb_serial_port *port);
-static int keyspan_ioctl (struct usb_serial_port *port,
- struct file *file,
- unsigned int cmd,
- unsigned long arg);
-static void keyspan_set_termios (struct usb_serial_port *port,
+static void keyspan_set_termios (struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old);
-static void keyspan_break_ctl (struct usb_serial_port *port,
+static void keyspan_break_ctl (struct tty_struct *tty,
int break_state);
-static int keyspan_tiocmget (struct usb_serial_port *port,
+static int keyspan_tiocmget (struct tty_struct *tty,
struct file *file);
-static int keyspan_tiocmset (struct usb_serial_port *port,
+static int keyspan_tiocmset (struct tty_struct *tty,
struct file *file, unsigned int set,
unsigned int clear);
static int keyspan_fake_startup (struct usb_serial *serial);
@@ -138,7 +135,8 @@ static int keyspan_usa67_send_setup (struct usb_serial *serial,
/* Product IDs post-renumeration. Note that the 28x and 28xb
have the same id's post-renumeration but behave identically
- so it's not an issue. */
+ so it's not an issue. As such, the 28xb is not listed in any
+ of the device tables. */
#define keyspan_usa18x_product_id 0x0112
#define keyspan_usa19_product_id 0x0107
#define keyspan_usa19qi_product_id 0x010c
@@ -482,7 +480,6 @@ static struct usb_device_id keyspan_ids_combined[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
- { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
@@ -532,7 +529,6 @@ static struct usb_device_id keyspan_2port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
- { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
{ } /* Terminating entry */
};
@@ -568,10 +564,6 @@ static struct usb_serial_driver keyspan_1port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
@@ -592,10 +584,6 @@ static struct usb_serial_driver keyspan_2port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
@@ -616,10 +604,6 @@ static struct usb_serial_driver keyspan_4port_device = {
.close = keyspan_close,
.write = keyspan_write,
.write_room = keyspan_write_room,
- .chars_in_buffer = keyspan_chars_in_buffer,
- .throttle = keyspan_rx_throttle,
- .unthrottle = keyspan_rx_unthrottle,
- .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 644a1eaaa37..040040a267d 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -10,8 +10,9 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- *
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
* (09/07/2001) gkh
* cleaned up the Xircom support. Added ids for Entregra device which is
* the same as the Xircom device. Enabled the code to be compiled for
@@ -21,23 +22,24 @@
* support for Xircom PGSDB9
*
* (05/31/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (08/28/2000) gkh
* Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
* than once.
- *
+ *
* (07/20/2000) borchers
* - keyspan_pda_write no longer sleeps if it is called on interrupt time;
* PPP and the line discipline with stty echo on can call write on
@@ -55,14 +57,14 @@
* than done directly from the callback to avoid the race in write_chan
* - keyspan_pda_chars_in_buffer also indicates its buffer is full if the
* urb status is -EINPROGRESS, meaning it cannot write at the moment
- *
+ *
* (07/19/2000) gkh
* Added module_init and module_exit functions to handle the fact that this
* driver is a loadable module now.
*
* (03/26/2000) gkh
* Split driver up into device specific pieces.
- *
+ *
*/
@@ -78,7 +80,7 @@
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -135,7 +137,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver keyspan_pda_driver = {
.name = "keyspan_pda",
@@ -159,9 +161,9 @@ static struct usb_device_id id_table_fake [] = {
#ifdef XIRCOM
static struct usb_device_id id_table_fake_xircom [] = {
- { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
- { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
- { }
+ { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
+ { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
+ { }
};
#endif
@@ -171,7 +173,7 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
container_of(work, struct keyspan_pda_private, wakeup_work);
struct usb_serial_port *port = priv->port;
- tty_wakeup(port->tty);
+ tty_wakeup(port->port.tty);
}
static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -184,7 +186,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
dbg(" request_unthrottle");
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
- result = usb_control_msg(serial->dev,
+ result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
7, /* request_unthrottle */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -195,17 +197,16 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
0,
2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
+ dbg("%s - error %d from usb_control_msg",
__func__, result);
}
-static void keyspan_pda_rx_interrupt (struct urb *urb)
+static void keyspan_pda_rx_interrupt(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int retval;
int status = urb->status;
struct keyspan_pda_private *priv;
@@ -228,14 +229,13 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
goto exit;
}
- /* see if the message is data or a status interrupt */
+ /* see if the message is data or a status interrupt */
switch (data[0]) {
case 0:
/* rest of message is rx data */
if (urb->actual_length) {
- for (i = 1; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data + 1,
+ urb->actual_length - 1);
tty_flip_buffer_push(tty);
}
break;
@@ -259,14 +259,14 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
}
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
}
-static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
+static void keyspan_pda_rx_throttle(struct tty_struct *tty)
{
/* stop receiving characters. We just turn off the URB request, and
let chars pile up in the device. If we're doing hardware
@@ -274,14 +274,15 @@ static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
fills up. If we're doing XON/XOFF, this would be a good time to
send an XOFF, although it might make sense to foist that off
upon the device too. */
-
+ struct usb_serial_port *port = tty->driver_data;
dbg("keyspan_pda_rx_throttle port %d", port->number);
usb_kill_urb(port->interrupt_in_urb);
}
-static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
+static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
/* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev;
@@ -291,32 +292,52 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
}
-static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
+static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
{
int rc;
int bindex;
- switch(baud) {
- case 110: bindex = 0; break;
- case 300: bindex = 1; break;
- case 1200: bindex = 2; break;
- case 2400: bindex = 3; break;
- case 4800: bindex = 4; break;
- case 9600: bindex = 5; break;
- case 19200: bindex = 6; break;
- case 38400: bindex = 7; break;
- case 57600: bindex = 8; break;
- case 115200: bindex = 9; break;
- default:
- bindex = 5; /* Default to 9600 */
- baud = 9600;
+ switch (baud) {
+ case 110:
+ bindex = 0;
+ break;
+ case 300:
+ bindex = 1;
+ break;
+ case 1200:
+ bindex = 2;
+ break;
+ case 2400:
+ bindex = 3;
+ break;
+ case 4800:
+ bindex = 4;
+ break;
+ case 9600:
+ bindex = 5;
+ break;
+ case 19200:
+ bindex = 6;
+ break;
+ case 38400:
+ bindex = 7;
+ break;
+ case 57600:
+ bindex = 8;
+ break;
+ case 115200:
+ bindex = 9;
+ break;
+ default:
+ bindex = 5; /* Default to 9600 */
+ baud = 9600;
}
/* rather than figure out how to sleep while waiting for this
to complete, I just use the "legacy" API. */
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0, /* set baud */
- USB_TYPE_VENDOR
+ USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
| USB_DIR_OUT, /* type */
bindex, /* value */
@@ -330,8 +351,9 @@ static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
}
-static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state)
+static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int value;
int result;
@@ -341,11 +363,11 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
else
value = 0; /* clear break */
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- 4, /* set break */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- value, 0, NULL, 0, 2000);
+ 4, /* set break */
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ value, 0, NULL, 0, 2000);
if (result < 0)
- dbg("%s - error %d from usb_control_msg",
+ dbg("%s - error %d from usb_control_msg",
__func__, result);
/* there is something funky about this.. the TCSBRK that 'cu' performs
ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
@@ -354,8 +376,8 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
}
-static void keyspan_pda_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void keyspan_pda_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
speed_t speed;
@@ -380,7 +402,7 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
For now, just do baud. */
- speed = tty_get_baud_rate(port->tty);
+ speed = tty_get_baud_rate(tty);
speed = keyspan_pda_setbaud(serial, speed);
if (speed == 0) {
@@ -390,8 +412,8 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
}
/* Only speed can change so copy the old h/w parameters
then encode the new speed */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- tty_encode_baud_rate(port->tty, speed, speed);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ tty_encode_baud_rate(tty, speed, speed);
}
@@ -408,7 +430,7 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial,
3, /* get pins */
USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
0, 0, &data, 1, 2000);
- if (rc > 0)
+ if (rc >= 0)
*value = data;
return rc;
}
@@ -425,8 +447,9 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
return rc;
}
-static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int rc;
unsigned char status;
@@ -445,9 +468,10 @@ static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
int rc;
unsigned char status;
@@ -469,23 +493,8 @@ static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
return rc;
}
-static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- return 0; /* TODO */
- }
-
- return -ENOIOCTLCMD;
-}
-
-static int keyspan_pda_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int keyspan_pda_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int request_unthrottle = 0;
@@ -501,10 +510,10 @@ static int keyspan_pda_write(struct usb_serial_port *port,
select() or poll() too) until we receive that unthrottle interrupt.
Block if we can't write anything at all, otherwise write as much as
we can. */
- dbg("keyspan_pda_write(%d)",count);
+ dbg("keyspan_pda_write(%d)", count);
if (count == 0) {
dbg(" write request of 0 bytes");
- return (0);
+ return 0;
}
/* we might block because of:
@@ -531,7 +540,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
scheduler time, since usb_control_msg() sleeps. */
if (count > priv->tx_room && !in_interrupt()) {
unsigned char room;
- rc = usb_control_msg(serial->dev,
+ rc = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
6, /* write_room */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -562,7 +571,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
if (count) {
/* now transfer data */
- memcpy (port->write_urb->transfer_buffer, buf, count);
+ memcpy(port->write_urb->transfer_buffer, buf, count);
/* send the data out the bulk port */
port->write_urb->transfer_buffer_length = count;
@@ -574,8 +583,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
dbg(" usb_submit_urb(write bulk) failed");
goto exit;
}
- }
- else {
+ } else {
/* There wasn't any room left, so we are throttled until
the buffer empties a bit */
request_unthrottle = 1;
@@ -594,7 +602,7 @@ exit:
}
-static void keyspan_pda_write_bulk_callback (struct urb *urb)
+static void keyspan_pda_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct keyspan_pda_private *priv;
@@ -607,22 +615,21 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb)
}
-static int keyspan_pda_write_room (struct usb_serial_port *port)
+static int keyspan_pda_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_pda_private *priv;
-
priv = usb_get_serial_port_data(port);
-
/* used by n_tty.c for processing of tabs and such. Giving it our
conservative guess is probably good enough, but needs testing by
running a console through the device. */
-
- return (priv->tx_room);
+ return priv->tx_room;
}
-static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
+static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct keyspan_pda_private *priv;
unsigned long flags;
int ret = 0;
@@ -640,7 +647,8 @@ static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
}
-static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_pda_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
unsigned char room;
@@ -672,8 +680,8 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
/* the normal serial device seems to always turn on DTR and RTS here,
so do the same */
- if (port->tty->termios->c_cflag & CBAUD)
- keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+ if (tty && (tty->termios->c_cflag & CBAUD))
+ keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
else
keyspan_pda_set_modem_info(serial, 0);
@@ -690,13 +698,15 @@ error:
}
-static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
if (serial->dev) {
- /* the normal serial device seems to always shut off DTR and RTS now */
- if (port->tty->termios->c_cflag & HUPCL)
+ /* the normal serial device seems to always shut
+ off DTR and RTS now */
+ if (tty->termios->c_cflag & HUPCL)
keyspan_pda_set_modem_info(serial, 0);
/* shutdown our bulk reads and writes */
@@ -707,7 +717,7 @@ static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
/* download the firmware to a "fake" device (pre-renumeration) */
-static int keyspan_pda_fake_startup (struct usb_serial *serial)
+static int keyspan_pda_fake_startup(struct usb_serial *serial)
{
int response;
const char *fw_name;
@@ -756,10 +766,10 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
response = ezusb_set_reset(serial, 0);
/* we want this device to fail to have a driver assigned to it. */
- return (1);
+ return 1;
}
-static int keyspan_pda_startup (struct usb_serial *serial)
+static int keyspan_pda_startup(struct usb_serial *serial)
{
struct keyspan_pda_private *priv;
@@ -769,20 +779,20 @@ static int keyspan_pda_startup (struct usb_serial *serial)
priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
if (!priv)
- return (1); /* error */
+ return 1; /* error */
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
priv->serial = serial;
priv->port = serial->port[0];
- return (0);
+ return 0;
}
-static void keyspan_pda_shutdown (struct usb_serial *serial)
+static void keyspan_pda_shutdown(struct usb_serial *serial)
{
dbg("%s", __func__);
-
+
kfree(usb_get_serial_port_data(serial->port[0]));
}
@@ -832,7 +842,6 @@ static struct usb_serial_driver keyspan_pda_device = {
.chars_in_buffer = keyspan_pda_chars_in_buffer,
.throttle = keyspan_pda_rx_throttle,
.unthrottle = keyspan_pda_rx_unthrottle,
- .ioctl = keyspan_pda_ioctl,
.set_termios = keyspan_pda_set_termios,
.break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
@@ -842,7 +851,7 @@ static struct usb_serial_driver keyspan_pda_device = {
};
-static int __init keyspan_pda_init (void)
+static int __init keyspan_pda_init(void)
{
int retval;
retval = usb_serial_register(&keyspan_pda_device);
@@ -863,7 +872,7 @@ static int __init keyspan_pda_init (void)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
-failed_usb_register:
+failed_usb_register:
#ifdef XIRCOM
usb_serial_deregister(&xircom_pgs_fake_device);
failed_xircom_register:
@@ -880,15 +889,15 @@ failed_pda_register:
}
-static void __exit keyspan_pda_exit (void)
+static void __exit keyspan_pda_exit(void)
{
- usb_deregister (&keyspan_pda_driver);
- usb_serial_deregister (&keyspan_pda_device);
+ usb_deregister(&keyspan_pda_driver);
+ usb_serial_deregister(&keyspan_pda_device);
#ifdef KEYSPAN
- usb_serial_deregister (&keyspan_pda_fake_device);
+ usb_serial_deregister(&keyspan_pda_fake_device);
#endif
#ifdef XIRCOM
- usb_serial_deregister (&xircom_pgs_fake_device);
+ usb_serial_deregister(&xircom_pgs_fake_device);
#endif
}
@@ -896,8 +905,8 @@ static void __exit keyspan_pda_exit (void)
module_init(keyspan_pda_init);
module_exit(keyspan_pda_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index f328948d74e..b84dddc7112 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -15,12 +15,12 @@
* Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided
* information that was not already available.
*
- * It seems that KLSI bought some silicon-design information from ScanLogic,
+ * It seems that KLSI bought some silicon-design information from ScanLogic,
* whose SL11R processor is at the core of the KL5KUSB chipset from KLSI.
* KLSI has firmware available for their devices; it is probable that the
* firmware differs from that used by KLSI in their products. If you have an
- * original KLSI device and can provide some information on it, I would be
- * most interested in adding support for it here. If you have any information
+ * original KLSI device and can provide some information on it, I would be
+ * most interested in adding support for it here. If you have any information
* on the protocol used (or find errors in my reverse-engineered stuff), please
* let me know.
*
@@ -40,7 +40,7 @@
* 0.2 - TIOCMGET works, so autopilot(1) can be used!
* 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l
*
- * The driver skeleton is mainly based on mct_u232.c and various other
+ * The driver skeleton is mainly based on mct_u232.c and various other
* pieces of code shamelessly copied from the drivers/usb/serial/ directory.
*/
@@ -53,7 +53,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/unaligned.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -72,33 +72,25 @@ static int debug;
/*
* Function prototypes
*/
-static int klsi_105_startup (struct usb_serial *serial);
-static void klsi_105_shutdown (struct usb_serial *serial);
-static int klsi_105_open (struct usb_serial_port *port,
- struct file *filp);
-static void klsi_105_close (struct usb_serial_port *port,
- struct file *filp);
-static int klsi_105_write (struct usb_serial_port *port,
- const unsigned char *buf,
- int count);
-static void klsi_105_write_bulk_callback (struct urb *urb);
-static int klsi_105_chars_in_buffer (struct usb_serial_port *port);
-static int klsi_105_write_room (struct usb_serial_port *port);
-
-static void klsi_105_read_bulk_callback (struct urb *urb);
-static void klsi_105_set_termios (struct usb_serial_port *port,
- struct ktermios *old);
-static void klsi_105_throttle (struct usb_serial_port *port);
-static void klsi_105_unthrottle (struct usb_serial_port *port);
-/*
-static void klsi_105_break_ctl (struct usb_serial_port *port,
- int break_state );
- */
-static int klsi_105_tiocmget (struct usb_serial_port *port,
- struct file *file);
-static int klsi_105_tiocmset (struct usb_serial_port *port,
- struct file *file, unsigned int set,
- unsigned int clear);
+static int klsi_105_startup(struct usb_serial *serial);
+static void klsi_105_shutdown(struct usb_serial *serial);
+static int klsi_105_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int klsi_105_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count);
+static void klsi_105_write_bulk_callback(struct urb *urb);
+static int klsi_105_chars_in_buffer(struct tty_struct *tty);
+static int klsi_105_write_room(struct tty_struct *tty);
+static void klsi_105_read_bulk_callback(struct urb *urb);
+static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static void klsi_105_throttle(struct tty_struct *tty);
+static void klsi_105_unthrottle(struct tty_struct *tty);
+static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
+static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
/*
* All of the device info needed for the KLSI converters.
@@ -109,7 +101,7 @@ static struct usb_device_id id_table [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver kl5kusb105d_driver = {
.name = "kl5kusb105d",
@@ -134,7 +126,7 @@ static struct usb_serial_driver kl5kusb105d_device = {
.write_bulk_callback = klsi_105_write_bulk_callback,
.chars_in_buffer = klsi_105_chars_in_buffer,
.write_room = klsi_105_write_room,
- .read_bulk_callback =klsi_105_read_bulk_callback,
+ .read_bulk_callback = klsi_105_read_bulk_callback,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
@@ -161,7 +153,7 @@ struct klsi_105_private {
struct ktermios termios;
unsigned long line_state; /* modem line settings */
/* write pool */
- struct urb * write_urb_pool[NUM_URBS];
+ struct urb *write_urb_pool[NUM_URBS];
spinlock_t lock;
unsigned long bytes_in;
unsigned long bytes_out;
@@ -180,15 +172,15 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
{
int rc;
- rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_SET_DATA,
- USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
- 0, /* value */
- 0, /* index */
- settings,
- sizeof(struct klsi_105_port_settings),
- KLSI_TIMEOUT);
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_SET_DATA,
+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
+ 0, /* value */
+ 0, /* index */
+ settings,
+ sizeof(struct klsi_105_port_settings),
+ KLSI_TIMEOUT);
if (rc < 0)
err("Change port settings failed (error = %d)", rc);
info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
@@ -196,7 +188,7 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
settings->pktlen,
settings->baudrate, settings->databits,
settings->unknown1, settings->unknown2);
- return rc;
+ return rc;
} /* klsi_105_chg_port_settings */
/* translate a 16-bit status value from the device to linux's TIO bits */
@@ -210,9 +202,9 @@ static unsigned long klsi_105_status2linestate(const __u16 status)
return res;
}
-/*
+/*
* Read line control via vendor command and return result through
- * *line_state_p
+ * *line_state_p
*/
/* It seems that the status buffer has always only 2 bytes length */
#define KLSI_STATUSBUF_LEN 2
@@ -220,14 +212,14 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
unsigned long *line_state_p)
{
int rc;
- __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+ __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
__u16 status;
info("%s - sending SIO Poll request", __func__);
- rc = usb_control_msg(port->serial->dev,
+ rc = usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_POLL,
- USB_TYPE_VENDOR | USB_DIR_IN,
+ USB_TYPE_VENDOR | USB_DIR_IN,
0, /* value */
0, /* index */
status_buf, KLSI_STATUSBUF_LEN,
@@ -236,15 +228,14 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
if (rc < 0)
err("Reading line status failed (error = %d)", rc);
else {
- status = le16_to_cpu(get_unaligned((__le16 *)status_buf));
+ status = get_unaligned_le16(status_buf);
info("%s - read status %x %x", __func__,
status_buf[0], status_buf[1]);
*line_state_p = klsi_105_status2linestate(status);
}
-
- return rc;
+ return rc;
}
@@ -252,7 +243,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
* Driver's tty interface functions
*/
-static int klsi_105_startup (struct usb_serial *serial)
+static int klsi_105_startup(struct usb_serial *serial)
{
struct klsi_105_private *priv;
int i, j;
@@ -262,7 +253,7 @@ static int klsi_105_startup (struct usb_serial *serial)
*/
/* allocate the private data structure */
- for (i=0; i<serial->num_ports; i++) {
+ for (i = 0; i < serial->num_ports; i++) {
priv = kmalloc(sizeof(struct klsi_105_private),
GFP_KERNEL);
if (!priv) {
@@ -283,9 +274,9 @@ static int klsi_105_startup (struct usb_serial *serial)
priv->bytes_out = 0;
usb_set_serial_port_data(serial->port[i], priv);
- spin_lock_init (&priv->lock);
- for (j=0; j<NUM_URBS; j++) {
- struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
+ spin_lock_init(&priv->lock);
+ for (j = 0; j < NUM_URBS; j++) {
+ struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
priv->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -293,10 +284,11 @@ static int klsi_105_startup (struct usb_serial *serial)
goto err_cleanup;
}
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
- GFP_KERNEL);
+ urb->transfer_buffer =
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (!urb->transfer_buffer) {
- err("%s - out of memory for urb buffers.", __func__);
+ err("%s - out of memory for urb buffers.",
+ __func__);
goto err_cleanup;
}
}
@@ -304,13 +296,13 @@ static int klsi_105_startup (struct usb_serial *serial)
/* priv->termios is left uninitalized until port opening */
init_waitqueue_head(&serial->port[i]->write_wait);
}
-
+
return 0;
err_cleanup:
for (; i >= 0; i--) {
priv = usb_get_serial_port_data(serial->port[i]);
- for (j=0; j < NUM_URBS; j++) {
+ for (j = 0; j < NUM_URBS; j++) {
if (priv->write_urb_pool[j]) {
kfree(priv->write_urb_pool[j]->transfer_buffer);
usb_free_urb(priv->write_urb_pool[j]);
@@ -322,22 +314,23 @@ err_cleanup:
} /* klsi_105_startup */
-static void klsi_105_shutdown (struct usb_serial *serial)
+static void klsi_105_shutdown(struct usb_serial *serial)
{
int i;
-
+
dbg("%s", __func__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
- struct klsi_105_private *priv = usb_get_serial_port_data(serial->port[i]);
+ for (i = 0; i < serial->num_ports; ++i) {
+ struct klsi_105_private *priv =
+ usb_get_serial_port_data(serial->port[i]);
unsigned long flags;
if (priv) {
/* kill our write urb pool */
int j;
struct urb **write_urbs = priv->write_urb_pool;
- spin_lock_irqsave(&priv->lock,flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (j = 0; j < NUM_URBS; j++) {
if (write_urbs[j]) {
@@ -349,19 +342,18 @@ static void klsi_105_shutdown (struct usb_serial *serial)
* oopses. */
/* usb_kill_urb(write_urbs[j]); */
kfree(write_urbs[j]->transfer_buffer);
- usb_free_urb (write_urbs[j]);
+ usb_free_urb(write_urbs[j]);
}
}
-
- spin_unlock_irqrestore (&priv->lock, flags);
-
+ spin_unlock_irqrestore(&priv->lock, flags);
kfree(priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
}
} /* klsi_105_shutdown */
-static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
+static int klsi_105_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int retval = 0;
@@ -375,11 +367,11 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
/* force low_latency on so that our tty_push actually forces
* the data through
- * port->tty->low_latency = 1; */
+ * tty->low_latency = 1; */
/* Do a defined restart:
* Set up sane default baud rate and send the 'READ_ON'
- * vendor command.
+ * vendor command.
* FIXME: set modem line control (how?)
* Then read the modem line control and store values in
* priv->line_state.
@@ -390,24 +382,24 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
cfg.unknown1 = 0;
cfg.unknown2 = 1;
klsi_105_chg_port_settings(port, &cfg);
-
+
/* set up termios structure */
- spin_lock_irqsave (&priv->lock, flags);
- priv->termios.c_iflag = port->tty->termios->c_iflag;
- priv->termios.c_oflag = port->tty->termios->c_oflag;
- priv->termios.c_cflag = port->tty->termios->c_cflag;
- priv->termios.c_lflag = port->tty->termios->c_lflag;
- for (i=0; i<NCCS; i++)
- priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->termios.c_iflag = tty->termios->c_iflag;
+ priv->termios.c_oflag = tty->termios->c_oflag;
+ priv->termios.c_cflag = tty->termios->c_cflag;
+ priv->termios.c_lflag = tty->termios->c_lflag;
+ for (i = 0; i < NCCS; i++)
+ priv->termios.c_cc[i] = tty->termios->c_cc[i];
priv->cfg.pktlen = cfg.pktlen;
priv->cfg.baudrate = cfg.baudrate;
priv->cfg.databits = cfg.databits;
priv->cfg.unknown1 = cfg.unknown1;
priv->cfg.unknown2 = cfg.unknown2;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
/* READ_ON and urb submission */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -423,7 +415,7 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
}
rc = usb_control_msg(port->serial->dev,
- usb_sndctrlpipe(port->serial->dev,0),
+ usb_sndctrlpipe(port->serial->dev, 0),
KL5KUSB105A_SIO_CONFIGURE,
USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
KL5KUSB105A_SIO_CONFIGURE_READ_ON,
@@ -434,14 +426,14 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
if (rc < 0) {
err("Enabling read failed (error = %d)", rc);
retval = rc;
- } else
+ } else
dbg("%s - enabled reading", __func__);
rc = klsi_105_get_line_state(port, &line_state);
if (rc >= 0) {
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - read line state 0x%lx", __func__, line_state);
retval = 0;
} else
@@ -452,7 +444,8 @@ exit:
} /* klsi_105_open */
-static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int rc;
@@ -462,14 +455,14 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* send READ_OFF */
- rc = usb_control_msg (port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_CONFIGURE,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
- 0, /* index */
- NULL, 0,
- KLSI_TIMEOUT);
+ rc = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
if (rc < 0)
err("Disabling read failed (error = %d)", rc);
}
@@ -482,23 +475,24 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
/* FIXME */
/* wgg - do I need this? I think so. */
usb_kill_urb(port->interrupt_in_urb);
- info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
+ info("kl5kusb105 port stats: %ld bytes in, %ld bytes out",
+ priv->bytes_in, priv->bytes_out);
} /* klsi_105_close */
/* We need to write a complete 64-byte data block and encode the
- * number actually sent in the first double-byte, LSB-order. That
+ * number actually sent in the first double-byte, LSB-order. That
* leaves at most 62 bytes of payload.
*/
#define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */
-static int klsi_105_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int klsi_105_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int result, size;
- int bytes_sent=0;
+ int bytes_sent = 0;
dbg("%s - port %d", __func__, port->number);
@@ -507,34 +501,37 @@ static int klsi_105_write (struct usb_serial_port *port,
struct urb *urb = NULL;
unsigned long flags;
int i;
- /* since the pool is per-port we might not need the spin lock !? */
- spin_lock_irqsave (&priv->lock, flags);
- for (i=0; i<NUM_URBS; i++) {
+ /* since the pool is per-port we might not need
+ the spin lock !? */
+ spin_lock_irqsave(&priv->lock, flags);
+ for (i = 0; i < NUM_URBS; i++) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
urb = priv->write_urb_pool[i];
dbg("%s - using pool URB %d", __func__, i);
break;
}
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
- if (urb==NULL) {
+ if (urb == NULL) {
dbg("%s - no more free urbs", __func__);
goto exit;
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+ urb->transfer_buffer =
+ kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err("%s - no more kernel memory...", __func__);
goto exit;
}
}
- size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
- size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET);
+ size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
+ size = min(size, URB_TRANSFER_BUFFER_SIZE -
+ KLSI_105_DATA_OFFSET);
- memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
+ memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
/* write payload size into transfer buffer */
((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);
@@ -552,7 +549,8 @@ static int klsi_105_write (struct usb_serial_port *port,
/* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
goto exit;
}
buf += size;
@@ -561,12 +559,12 @@ static int klsi_105_write (struct usb_serial_port *port,
}
exit:
/* lockless, but it's for debug info only... */
- priv->bytes_out+=bytes_sent;
+ priv->bytes_out += bytes_sent;
return bytes_sent; /* that's how much we wrote */
} /* klsi_105_write */
-static void klsi_105_write_bulk_callback ( struct urb *urb)
+static void klsi_105_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -584,50 +582,50 @@ static void klsi_105_write_bulk_callback ( struct urb *urb)
/* return number of characters currently in the writing process */
-static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+static int klsi_105_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int chars = 0;
int i;
unsigned long flags;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
+ if (priv->write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - returns %d", __func__, chars);
- return (chars);
+ return chars;
}
-static int klsi_105_write_room (struct usb_serial_port *port)
+static int klsi_105_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned long flags;
int i;
int room = 0;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+ if (priv->write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
- }
}
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - returns %d", __func__, room);
- return (room);
+ return room;
}
-static void klsi_105_read_bulk_callback (struct urb *urb)
+static void klsi_105_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -660,13 +658,13 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
} else {
int bytes_sent = ((__u8 *) data)[0] +
((unsigned int) ((__u8 *) data)[1] << 8);
- tty = port->tty;
+ tty = port->port.tty;
/* we should immediately resubmit the URB, before attempting
* to pass the data on to the tty layer. But that needs locking
* against re-entry an then mixed-up data because of
* intermixed tty_flip_buffer_push()s
* FIXME
- */
+ */
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
@@ -686,7 +684,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
priv->bytes_in += bytes_sent;
}
/* Continue trying to always read */
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
@@ -695,15 +693,16 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port);
rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
- err("%s - failed resubmitting read urb, error %d", __func__, rc);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, rc);
} /* klsi_105_read_bulk_callback */
-static void klsi_105_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void klsi_105_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
unsigned int iflag = tty->termios->c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag;
@@ -711,65 +710,63 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
struct klsi_105_port_settings cfg;
unsigned long flags;
speed_t baud;
-
+
/* lock while we are modifying the settings */
- spin_lock_irqsave (&priv->lock, flags);
-
+ spin_lock_irqsave(&priv->lock, flags);
+
/*
* Update baud rate
*/
baud = tty_get_baud_rate(tty);
- if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
- /* reassert DTR and (maybe) RTS on transition from B0 */
- if( (old_cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
+ /* reassert DTR and (maybe) RTS on transition from B0 */
+ if ((old_cflag & CBAUD) == B0) {
dbg("%s: baud was B0", __func__);
#if 0
priv->control_state |= TIOCM_DTR;
/* don't set RTS if using hardware flow control */
- if (!(old_cflag & CRTSCTS)) {
+ if (!(old_cflag & CRTSCTS))
priv->control_state |= TIOCM_RTS;
- }
mct_u232_set_modem_ctrl(serial, priv->control_state);
#endif
}
}
- switch(baud) {
- case 0: /* handled below */
- break;
- case 1200:
- priv->cfg.baudrate = kl5kusb105a_sio_b1200;
- break;
- case 2400:
- priv->cfg.baudrate = kl5kusb105a_sio_b2400;
- break;
- case 4800:
- priv->cfg.baudrate = kl5kusb105a_sio_b4800;
- break;
- case 9600:
- priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- break;
- case 19200:
- priv->cfg.baudrate = kl5kusb105a_sio_b19200;
- break;
- case 38400:
- priv->cfg.baudrate = kl5kusb105a_sio_b38400;
- break;
- case 57600:
- priv->cfg.baudrate = kl5kusb105a_sio_b57600;
- break;
- case 115200:
- priv->cfg.baudrate = kl5kusb105a_sio_b115200;
- break;
- default:
- dbg("KLSI USB->Serial converter:"
- " unsupported baudrate request, using default"
- " of 9600");
+ switch (baud) {
+ case 0: /* handled below */
+ break;
+ case 1200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b1200;
+ break;
+ case 2400:
+ priv->cfg.baudrate = kl5kusb105a_sio_b2400;
+ break;
+ case 4800:
+ priv->cfg.baudrate = kl5kusb105a_sio_b4800;
+ break;
+ case 9600:
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ break;
+ case 19200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b19200;
+ break;
+ case 38400:
+ priv->cfg.baudrate = kl5kusb105a_sio_b38400;
+ break;
+ case 57600:
+ priv->cfg.baudrate = kl5kusb105a_sio_b57600;
+ break;
+ case 115200:
+ priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+ break;
+ default:
+ dbg("KLSI USB->Serial converter:"
+ " unsupported baudrate request, using default of 9600");
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- baud = 9600;
- break;
+ baud = 9600;
+ break;
}
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
dbg("%s: baud is B0", __func__);
/* Drop RTS and DTR */
/* maybe this should be simulated by sending read
@@ -778,7 +775,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
;
#if 0
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- mct_u232_set_modem_ctrl(serial, priv->control_state);
+ mct_u232_set_modem_ctrl(serial, priv->control_state);
#endif
}
tty_encode_baud_rate(tty, baud, baud);
@@ -788,11 +785,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
switch (cflag & CSIZE) {
case CS5:
dbg("%s - 5 bits/byte not supported", __func__);
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return ;
case CS6:
dbg("%s - 6 bits/byte not supported", __func__);
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return ;
case CS7:
priv->cfg.databits = kl5kusb105a_dtb_7;
@@ -811,8 +808,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
* Update line control register (LCR)
*/
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
- || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
-
+ || (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
/* Not currently supported */
tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
#if 0
@@ -833,20 +829,18 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif
;
}
-
/*
* Set flow control: well, I do not really now how to handle DTR/RTS.
* Just do what we have seen with SniffUSB on Win98.
*/
- if( (iflag & IXOFF) != (old_iflag & IXOFF)
+ if ((iflag & IXOFF) != (old_iflag & IXOFF)
|| (iflag & IXON) != (old_iflag & IXON)
- || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
-
+ || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
/* Not currently supported */
tty->termios->c_cflag &= ~CRTSCTS;
/* Drop DTR/RTS if no flow control otherwise assert */
#if 0
- if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+ if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
priv->control_state |= TIOCM_DTR | TIOCM_RTS;
else
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -854,19 +848,21 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif
;
}
- memcpy (&cfg, &priv->cfg, sizeof(cfg));
- spin_unlock_irqrestore (&priv->lock, flags);
-
+ memcpy(&cfg, &priv->cfg, sizeof(cfg));
+ spin_unlock_irqrestore(&priv->lock, flags);
+
/* now commit changes to device */
klsi_105_chg_port_settings(port, &cfg);
} /* klsi_105_set_termios */
#if 0
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv =
+ (struct mct_u232_private *)port->private;
unsigned char lcr = priv->last_lcr;
dbg("%sstate=%d", __func__, break_state);
@@ -878,8 +874,9 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
#endif
-static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int rc;
@@ -893,18 +890,18 @@ static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
return rc;
}
- spin_lock_irqsave (&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_state = line_state;
- spin_unlock_irqrestore (&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
dbg("%s - read line state 0x%lx", __func__, line_state);
return (int)line_state;
}
-static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear)
+static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
{
int retval = -EINVAL;
-
+
dbg("%s", __func__);
/* if this ever gets implemented, it should be done something like this:
@@ -929,14 +926,16 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
return retval;
}
-static void klsi_105_throttle (struct usb_serial_port *port)
+static void klsi_105_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
}
-static void klsi_105_unthrottle (struct usb_serial_port *port)
+static void klsi_105_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int result;
dbg("%s - port %d", __func__, port->number);
@@ -950,7 +949,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
-static int __init klsi_105_init (void)
+static int __init klsi_105_init(void)
{
int retval;
retval = usb_serial_register(&kl5kusb105d_device);
@@ -969,19 +968,19 @@ failed_usb_serial_register:
}
-static void __exit klsi_105_exit (void)
+static void __exit klsi_105_exit(void)
{
- usb_deregister (&kl5kusb105d_driver);
- usb_serial_deregister (&kl5kusb105d_device);
+ usb_deregister(&kl5kusb105d_driver);
+ usb_serial_deregister(&kl5kusb105d_device);
}
-module_init (klsi_105_init);
-module_exit (klsi_105_exit);
+module_init(klsi_105_init);
+module_exit(klsi_105_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 693f00da7c0..deba28ec77e 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -1,7 +1,7 @@
/*
* KOBIL USB Smart Card Terminal Driver
*
- * Copyright (C) 2002 KOBIL Systems GmbH
+ * Copyright (C) 2002 KOBIL Systems GmbH
* Author: Thomas Wahrenbruch
*
* Contact: linuxusb@kobil.de
@@ -20,7 +20,7 @@
*
* Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
* (Adapter K), B1 Professional and KAAN Professional (Adapter B)
- *
+ *
* (21/05/2004) tw
* Fix bug with P'n'P readers
*
@@ -44,7 +44,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/ioctl.h>
@@ -68,21 +68,24 @@ static int debug;
/* Function prototypes */
-static int kobil_startup (struct usb_serial *serial);
-static void kobil_shutdown (struct usb_serial *serial);
-static int kobil_open (struct usb_serial_port *port, struct file *filp);
-static void kobil_close (struct usb_serial_port *port, struct file *filp);
-static int kobil_write (struct usb_serial_port *port,
+static int kobil_startup(struct usb_serial *serial);
+static void kobil_shutdown(struct usb_serial *serial);
+static int kobil_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-static int kobil_write_room(struct usb_serial_port *port);
-static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
+static int kobil_write_room(struct tty_struct *tty);
+static int kobil_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
-static int kobil_tiocmget(struct usb_serial_port *port, struct file *file);
-static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int kobil_tiocmget(struct tty_struct *tty, struct file *file);
+static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static void kobil_read_int_callback( struct urb *urb );
-static void kobil_write_callback( struct urb *purb );
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old);
+static void kobil_read_int_callback(struct urb *urb);
+static void kobil_write_callback(struct urb *purb);
+static void kobil_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
static struct usb_device_id id_table [] = {
@@ -94,7 +97,7 @@ static struct usb_device_id id_table [] = {
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver kobil_driver = {
.name = "kobil",
@@ -131,14 +134,14 @@ static struct usb_serial_driver kobil_device = {
struct kobil_private {
int write_int_endpoint_address;
int read_int_endpoint_address;
- unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send
- int filled; // index of the last char in buf
- int cur_pos; // index of the next char to send in buf
+ unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
+ int filled; /* index of the last char in buf */
+ int cur_pos; /* index of the next char to send in buf */
__u16 device_type;
};
-static int kobil_startup (struct usb_serial *serial)
+static int kobil_startup(struct usb_serial *serial)
{
int i;
struct kobil_private *priv;
@@ -149,20 +152,20 @@ static int kobil_startup (struct usb_serial *serial)
struct usb_host_endpoint *endpoint;
priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
- if (!priv){
+ if (!priv)
return -ENOMEM;
- }
priv->filled = 0;
priv->cur_pos = 0;
priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
- switch (priv->device_type){
+ switch (priv->device_type) {
case KOBIL_ADAPTER_B_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n");
break;
case KOBIL_ADAPTER_K_PRODUCT_ID:
- printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
+ printk(KERN_DEBUG
+ "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
break;
case KOBIL_USBTWIN_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
@@ -173,44 +176,48 @@ static int kobil_startup (struct usb_serial *serial)
}
usb_set_serial_port_data(serial->port[0], priv);
- // search for the necessary endpoints
+ /* search for the necessary endpoints */
pdev = serial->dev;
- actconfig = pdev->actconfig;
- interface = actconfig->interface[0];
+ actconfig = pdev->actconfig;
+ interface = actconfig->interface[0];
altsetting = interface->cur_altsetting;
- endpoint = altsetting->endpoint;
-
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+ endpoint = altsetting->endpoint;
+
+ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
endpoint = &altsetting->endpoint[i];
if (usb_endpoint_is_int_out(&endpoint->desc)) {
- dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
- priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
- }
+ dbg("%s Found interrupt out endpoint. Address: %d",
+ __func__, endpoint->desc.bEndpointAddress);
+ priv->write_int_endpoint_address =
+ endpoint->desc.bEndpointAddress;
+ }
if (usb_endpoint_is_int_in(&endpoint->desc)) {
- dbg("%s Found interrupt in endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
- priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
- }
+ dbg("%s Found interrupt in endpoint. Address: %d",
+ __func__, endpoint->desc.bEndpointAddress);
+ priv->read_int_endpoint_address =
+ endpoint->desc.bEndpointAddress;
+ }
}
return 0;
}
-static void kobil_shutdown (struct usb_serial *serial)
+static void kobil_shutdown(struct usb_serial *serial)
{
int i;
dbg("%s - port %d", __func__, serial->port[0]->number);
- for (i=0; i < serial->num_ports; ++i) {
- while (serial->port[i]->open_count > 0) {
- kobil_close (serial->port[i], NULL);
- }
+ for (i = 0; i < serial->num_ports; ++i) {
+ while (serial->port[i]->port.count > 0)
+ kobil_close(NULL, serial->port[i], NULL);
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
}
-static int kobil_open (struct usb_serial_port *port, struct file *filp)
+static int kobil_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int result = 0;
struct kobil_private *priv;
@@ -221,7 +228,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
priv = usb_get_serial_port_data(port);
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
@@ -229,100 +236,115 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
*/
- port->tty->low_latency = 1;
-
- // without this, every push_tty_char is echoed :-(
- port->tty->termios->c_lflag = 0;
- port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
- port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
- port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)
-
- // allocate memory for transfer buffer
+ if (tty) {
+ tty->low_latency = 1;
+
+ /* Default to echo off and other sane device settings */
+ tty->termios->c_lflag = 0;
+ tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
+ XCASE);
+ tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+ /* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
+ tty->termios->c_oflag &= ~ONLCR;
+ }
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
-
- // allocate write_urb
- if (!port->write_urb) {
- dbg("%s - port %d Allocating port->write_urb", __func__, port->number);
- port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ /* allocate write_urb */
+ if (!port->write_urb) {
+ dbg("%s - port %d Allocating port->write_urb",
+ __func__, port->number);
+ port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->write_urb) {
- dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
+ dbg("%s - port %d usb_alloc_urb failed",
+ __func__, port->number);
kfree(transfer_buffer);
return -ENOMEM;
}
}
- // allocate memory for write_urb transfer buffer
- port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
- if (! port->write_urb->transfer_buffer) {
+ /* allocate memory for write_urb transfer buffer */
+ port->write_urb->transfer_buffer =
+ kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+ if (!port->write_urb->transfer_buffer) {
kfree(transfer_buffer);
usb_free_urb(port->write_urb);
port->write_urb = NULL;
return -ENOMEM;
- }
-
- // get hardware version
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetMisc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- SUSBCR_MSC_GetHWVersion,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT
+ }
+
+ /* get hardware version */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetMisc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ SUSBCR_MSC_GetHWVersion,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+ dbg("%s - port %d Send get_HW_version URB returns: %i",
+ __func__, port->number, result);
+ dbg("Harware version: %i.%i.%i",
+ transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+ /* get firmware version */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetMisc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ SUSBCR_MSC_GetFWVersion,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT
+ );
+ dbg("%s - port %d Send get_FW_version URB returns: %i",
+ __func__, port->number, result);
+ dbg("Firmware version: %i.%i.%i",
+ transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+ /* Setting Baudrate, Parity and Stopbits */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetBaudRateParityAndStopBits,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
+ SUSBCR_SPASB_1StopBit,
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
- dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-
- // get firmware version
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetMisc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- SUSBCR_MSC_GetFWVersion,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT
+ dbg("%s - port %d Send set_baudrate URB returns: %i",
+ __func__, port->number, result);
+
+ /* reset all queues */
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_Misc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_MSC_ResetAllQueues,
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT
);
- dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
- dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-
- if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
- // Setting Baudrate, Parity and Stopbits
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetBaudRateParityAndStopBits,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit,
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT
- );
- dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
-
- // reset all queues
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_Misc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_MSC_ResetAllQueues,
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT
- );
- dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send reset_all_queues URB returns: %i",
+ __func__, port->number, result);
}
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
- // start reading (Adapter B 'cause PNP string)
- result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC );
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ /* start reading (Adapter B 'cause PNP string) */
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
kfree(transfer_buffer);
@@ -330,13 +352,14 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
}
-static void kobil_close (struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
if (port->write_urb) {
usb_kill_urb(port->write_urb);
- usb_free_urb( port->write_urb );
+ usb_free_urb(port->write_urb);
port->write_urb = NULL;
}
usb_kill_urb(port->interrupt_in_urb);
@@ -350,7 +373,7 @@ static void kobil_read_int_callback(struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
-// char *dbg_data;
+/* char *dbg_data; */
dbg("%s - port %d", __func__, port->number);
@@ -360,51 +383,53 @@ static void kobil_read_int_callback(struct urb *urb)
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- // BEGIN DEBUG
+ /* BEGIN DEBUG */
/*
- dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
+ dbg_data = kzalloc((3 * purb->actual_length + 10)
+ * sizeof(char), GFP_KERNEL);
if (! dbg_data) {
- return;
+ return;
}
- for (i = 0; i < purb->actual_length; i++) {
- sprintf(dbg_data +3*i, "%02X ", data[i]);
+ for (i = 0; i < purb->actual_length; i++) {
+ sprintf(dbg_data +3*i, "%02X ", data[i]);
}
- dbg(" <-- %s", dbg_data );
+ dbg(" <-- %s", dbg_data);
kfree(dbg_data);
*/
- // END DEBUG
+ /* END DEBUG */
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
-
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method has been called */
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
-static void kobil_write_callback( struct urb *purb )
+static void kobil_write_callback(struct urb *purb)
{
}
-static int kobil_write (struct usb_serial_port *port,
+static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
int length = 0;
int result = 0;
int todo = 0;
- struct kobil_private * priv;
+ struct kobil_private *priv;
if (count == 0) {
- dbg("%s - port %d write request of 0 bytes", __func__, port->number);
+ dbg("%s - port %d write request of 0 bytes",
+ __func__, port->number);
return 0;
}
@@ -415,106 +440,113 @@ static int kobil_write (struct usb_serial_port *port,
return -ENOMEM;
}
- // Copy data to buffer
- memcpy (priv->buf + priv->filled, buf, count);
-
- usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
-
+ /* Copy data to buffer */
+ memcpy(priv->buf + priv->filled, buf, count);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ priv->buf + priv->filled);
priv->filled = priv->filled + count;
-
- // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol.
- if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
- ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) {
-
- // stop reading (except TWIN and KAAN SIM)
- if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) )
+ /* only send complete block. TWIN, KAAN SIM and adapter K
+ use the same protocol. */
+ if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
+ ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) {
+ /* stop reading (except TWIN and KAAN SIM) */
+ if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID)
+ || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID))
usb_kill_urb(port->interrupt_in_urb);
todo = priv->filled - priv->cur_pos;
- while(todo > 0) {
- // max 8 byte in one urb (endpoint size)
+ while (todo > 0) {
+ /* max 8 byte in one urb (endpoint size) */
length = (todo < 8) ? todo : 8;
- // copy data to transfer buffer
- memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length );
- usb_fill_int_urb( port->write_urb,
- port->serial->dev,
- usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address),
- port->write_urb->transfer_buffer,
- length,
- kobil_write_callback,
- port,
- 8
- );
+ /* copy data to transfer buffer */
+ memcpy(port->write_urb->transfer_buffer,
+ priv->buf + priv->cur_pos, length);
+ usb_fill_int_urb(port->write_urb,
+ port->serial->dev,
+ usb_sndintpipe(port->serial->dev,
+ priv->write_int_endpoint_address),
+ port->write_urb->transfer_buffer,
+ length,
+ kobil_write_callback,
+ port,
+ 8
+ );
priv->cur_pos = priv->cur_pos + length;
- result = usb_submit_urb( port->write_urb, GFP_NOIO );
- dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
+ result = usb_submit_urb(port->write_urb, GFP_NOIO);
+ dbg("%s - port %d Send write URB returns: %i",
+ __func__, port->number, result);
todo = priv->filled - priv->cur_pos;
- if (todo > 0) {
+ if (todo > 0)
msleep(24);
- }
+ }
- } // end while
-
priv->filled = 0;
priv->cur_pos = 0;
- // someone sets the dev to 0 if the close method has been called
+ /* someone sets the dev to 0 if the close method
+ has been called */
port->interrupt_in_urb->dev = port->serial->dev;
-
- // start reading (except TWIN and KAAN SIM)
- if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) {
- // someone sets the dev to 0 if the close method has been called
+
+ /* start reading (except TWIN and KAAN SIM) */
+ if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+ priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+ /* someone sets the dev to 0 if the close method has
+ been called */
port->interrupt_in_urb->dev = port->serial->dev;
-
- result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO );
- dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+
+ result = usb_submit_urb(port->interrupt_in_urb,
+ GFP_NOIO);
+ dbg("%s - port %d Send read URB returns: %i",
+ __func__, port->number, result);
}
}
return count;
}
-static int kobil_write_room (struct usb_serial_port *port)
+static int kobil_write_room(struct tty_struct *tty)
{
- //dbg("%s - port %d", __func__, port->number);
+ /* dbg("%s - port %d", __func__, port->number); */
+ /* FIXME */
return 8;
}
-static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct kobil_private * priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv;
int result;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port);
- if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+ || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
return -EINVAL;
}
- // allocate memory for transfer buffer
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (!transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_GetStatusLineState,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
- 0,
- 0,
- transfer_buffer,
- transfer_buffer_length,
- KOBIL_TIMEOUT);
-
- dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_GetStatusLineState,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+ 0,
+ 0,
+ transfer_buffer,
+ transfer_buffer_length,
+ KOBIL_TIMEOUT);
+
+ dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
__func__, port->number, result, transfer_buffer[0]);
result = 0;
@@ -524,10 +556,11 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct kobil_private * priv;
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv;
int result;
int dtr = 0;
int rts = 0;
@@ -536,16 +569,16 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
/* FIXME: locking ? */
priv = usb_get_serial_port_data(port);
- if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+ || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
return -EINVAL;
}
- // allocate memory for transfer buffer
+ /* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer) {
+ if (!transfer_buffer)
return -ENOMEM;
- }
if (set & TIOCM_RTS)
rts = 1;
@@ -558,66 +591,77 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
if (dtr != 0)
- dbg("%s - port %d Setting DTR", __func__, port->number);
+ dbg("%s - port %d Setting DTR",
+ __func__, port->number);
else
- dbg("%s - port %d Clearing DTR", __func__, port->number);
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetStatusLinesOrQueues,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT);
+ dbg("%s - port %d Clearing DTR",
+ __func__, port->number);
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetStatusLinesOrQueues,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT);
} else {
if (rts != 0)
- dbg("%s - port %d Setting RTS", __func__, port->number);
+ dbg("%s - port %d Setting RTS",
+ __func__, port->number);
else
- dbg("%s - port %d Clearing RTS", __func__, port->number);
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetStatusLinesOrQueues,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
- 0,
- transfer_buffer,
- 0,
- KOBIL_TIMEOUT);
+ dbg("%s - port %d Clearing RTS",
+ __func__, port->number);
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetStatusLinesOrQueues,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
+ 0,
+ transfer_buffer,
+ 0,
+ KOBIL_TIMEOUT);
}
- dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
+ dbg("%s - port %d Send set_status_line URB returns: %i",
+ __func__, port->number, result);
kfree(transfer_buffer);
return (result < 0) ? result : 0;
}
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old)
+static void kobil_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old)
{
- struct kobil_private * priv;
+ struct kobil_private *priv;
int result;
unsigned short urb_val = 0;
- int c_cflag = port->tty->termios->c_cflag;
+ int c_cflag = tty->termios->c_cflag;
speed_t speed;
- void * settings;
+ void *settings;
priv = usb_get_serial_port_data(port);
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
- // This device doesn't support ioctl calls
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+ /* This device doesn't support ioctl calls */
+ *tty->termios = *old;
return;
+ }
- switch (speed = tty_get_baud_rate(port->tty)) {
- case 1200:
- urb_val = SUSBCR_SBR_1200;
- break;
- default:
- speed = 9600;
- case 9600:
- urb_val = SUSBCR_SBR_9600;
- break;
+ speed = tty_get_baud_rate(tty);
+ switch (speed) {
+ case 1200:
+ urb_val = SUSBCR_SBR_1200;
+ break;
+ default:
+ speed = 9600;
+ case 9600:
+ urb_val = SUSBCR_SBR_9600;
+ break;
}
- urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
+ urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
+ SUSBCR_SPASB_1StopBit;
settings = kzalloc(50, GFP_KERNEL);
- if (! settings)
+ if (!settings)
return;
sprintf(settings, "%d ", speed);
@@ -634,66 +678,69 @@ static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old
urb_val |= SUSBCR_SPASB_NoParity;
strcat(settings, "No Parity");
}
- port->tty->termios->c_cflag &= ~CMSPAR;
- tty_encode_baud_rate(port->tty, speed, speed);
-
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_SetBaudRateParityAndStopBits,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- urb_val,
- 0,
- settings,
- 0,
- KOBIL_TIMEOUT
+ tty->termios->c_cflag &= ~CMSPAR;
+ tty_encode_baud_rate(tty, speed, speed);
+
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_SetBaudRateParityAndStopBits,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ urb_val,
+ 0,
+ settings,
+ 0,
+ KOBIL_TIMEOUT
);
kfree(settings);
}
-static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct kobil_private * priv = usb_get_serial_port_data(port);
+ struct usb_serial_port *port = tty->driver_data;
+ struct kobil_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
int result;
- if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
- // This device doesn't support ioctl calls
- return 0;
+ if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+ priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
+ /* This device doesn't support ioctl calls */
+ return -ENOIOCTLCMD;
switch (cmd) {
- case TCFLSH: // 0x540B
+ case TCFLSH:
transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
- if (! transfer_buffer)
- return -ENOBUFS;
-
- result = usb_control_msg( port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0 ),
- SUSBCRequest_Misc,
- USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- SUSBCR_MSC_ResetAllQueues,
- 0,
- NULL,//transfer_buffer,
- 0,
- KOBIL_TIMEOUT
+ if (!transfer_buffer)
+ return -ENOBUFS;
+
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ SUSBCRequest_Misc,
+ USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+ SUSBCR_MSC_ResetAllQueues,
+ 0,
+ NULL, /* transfer_buffer, */
+ 0,
+ KOBIL_TIMEOUT
);
-
+
dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
kfree(transfer_buffer);
- return (result < 0) ? -EFAULT : 0;
+ return (result < 0) ? -EIO: 0;
default:
return -ENOIOCTLCMD;
}
}
-static int __init kobil_init (void)
+static int __init kobil_init(void)
{
int retval;
retval = usb_serial_register(&kobil_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&kobil_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -707,18 +754,18 @@ failed_usb_serial_register:
}
-static void __exit kobil_exit (void)
+static void __exit kobil_exit(void)
{
- usb_deregister (&kobil_driver);
- usb_serial_deregister (&kobil_device);
+ usb_deregister(&kobil_driver);
+ usb_serial_deregister(&kobil_device);
}
module_init(kobil_init);
module_exit(kobil_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( "GPL" );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 5fc2cef30e3..0ded8bd6ec8 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -33,10 +33,11 @@
* - Fixed an endianess problem with the baudrate selection for PowerPC.
*
* 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
- * Added support for the Belkin F5U109 DB9 adaptor
+ * - Added support for the Belkin F5U109 DB9 adaptor
*
* 30-May-2001 Greg Kroah-Hartman
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * - switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* 04-May-2001 Stelian Pop
* - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
@@ -49,7 +50,7 @@
* 08-Apr-2001 gb
* - Identify version on module load.
*
- * 06-Jan-2001 Cornel Ciocirlan
+ * 06-Jan-2001 Cornel Ciocirlan
* - Added support for Sitecom U232-P25 model (Product Id 0x0230)
* - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
*
@@ -59,8 +60,8 @@
* (lots of things will change if/when the usb-serial core changes to
* handle these issues.
*
- * 27-Nov-2000 Wolfgang Grandegger
- * A version for kernel 2.4.0-test10 released to the Linux community
+ * 27-Nov-2000 Wolfgang Grandegge
+ * A version for kernel 2.4.0-test10 released to the Linux community
* (via linux-usb-devel).
*/
@@ -73,7 +74,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "mct_u232.h"
@@ -90,28 +91,21 @@ static int debug;
/*
* Function prototypes
*/
-static int mct_u232_startup (struct usb_serial *serial);
-static void mct_u232_shutdown (struct usb_serial *serial);
-static int mct_u232_open (struct usb_serial_port *port,
- struct file *filp);
-static void mct_u232_close (struct usb_serial_port *port,
- struct file *filp);
-static void mct_u232_read_int_callback (struct urb *urb);
-static void mct_u232_set_termios (struct usb_serial_port *port,
- struct ktermios * old);
-static int mct_u232_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
-static void mct_u232_break_ctl (struct usb_serial_port *port,
- int break_state );
-static int mct_u232_tiocmget (struct usb_serial_port *port,
- struct file *file);
-static int mct_u232_tiocmset (struct usb_serial_port *port,
- struct file *file, unsigned int set,
- unsigned int clear);
-static void mct_u232_throttle (struct usb_serial_port *port);
-static void mct_u232_unthrottle (struct usb_serial_port *port);
+static int mct_u232_startup(struct usb_serial *serial);
+static void mct_u232_shutdown(struct usb_serial *serial);
+static int mct_u232_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void mct_u232_read_int_callback(struct urb *urb);
+static void mct_u232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
+static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file);
+static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void mct_u232_throttle(struct tty_struct *tty);
+static void mct_u232_unthrottle(struct tty_struct *tty);
/*
@@ -125,7 +119,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver mct_u232_driver = {
.name = "mct_u232",
@@ -149,7 +143,6 @@ static struct usb_serial_driver mct_u232_device = {
.throttle = mct_u232_throttle,
.unthrottle = mct_u232_unthrottle,
.read_int_callback = mct_u232_read_int_callback,
- .ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios,
.break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
@@ -180,23 +173,34 @@ struct mct_u232_private {
* Later day 2.6.0-test kernels have new baud rates like B230400 which
* we do not know how to support. We ignore them for the moment.
*/
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
+ speed_t value, speed_t *result)
{
*result = value;
if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
- || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
+ || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
- case 300: return 0x01;
- case 600: return 0x02; /* this one not tested */
- case 1200: return 0x03;
- case 2400: return 0x04;
- case 4800: return 0x06;
- case 9600: return 0x08;
- case 19200: return 0x09;
- case 38400: return 0x0a;
- case 57600: return 0x0b;
- case 115200: return 0x0c;
+ case 300:
+ return 0x01;
+ case 600:
+ return 0x02; /* this one not tested */
+ case 1200:
+ return 0x03;
+ case 2400:
+ return 0x04;
+ case 4800:
+ return 0x06;
+ case 9600:
+ return 0x08;
+ case 19200:
+ return 0x09;
+ case 38400:
+ return 0x0a;
+ case 57600:
+ return 0x0b;
+ case 115200:
+ return 0x0c;
default:
*result = 9600;
return 0x08;
@@ -224,26 +228,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value
}
}
-static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
- speed_t value)
+static int mct_u232_set_baud_rate(struct tty_struct *tty,
+ struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
{
__le32 divisor;
- int rc;
- unsigned char zero_byte = 0;
- unsigned char cts_enable_byte = 0;
- speed_t speed;
-
- divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
-
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_BAUD_RATE_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ unsigned char zero_byte = 0;
+ unsigned char cts_enable_byte = 0;
+ speed_t speed;
+
+ divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value,
+ &speed));
+
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_BAUD_RATE_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+ WDR_TIMEOUT);
if (rc < 0) /*FIXME: What value speed results */
err("Set BAUD RATE %d failed (error = %d)", value, rc);
else
- tty_encode_baud_rate(port->tty, speed, speed);
+ tty_encode_baud_rate(tty, speed, speed);
dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
@@ -258,55 +263,55 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_p
whether data will be transmitted to a device which is not asserting
the 'CTS' signal. If the second message's data byte is zero, data
will be transmitted even if 'CTS' is not asserted (i.e. no hardware
- flow control). if the second message's data byte is nonzero (a value
- of 1 is used by this driver), data will not be transmitted to a device
- which is not asserting 'CTS'.
+ flow control). if the second message's data byte is nonzero (a
+ value of 1 is used by this driver), data will not be transmitted to
+ a device which is not asserting 'CTS'.
*/
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_UNKNOWN1_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
- WDR_TIMEOUT);
+ MCT_U232_SET_UNKNOWN1_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
+ err("Sending USB device request code %d failed (error = %d)",
MCT_U232_SET_UNKNOWN1_REQUEST, rc);
- if (port && C_CRTSCTS(port->tty)) {
+ if (port && C_CRTSCTS(tty))
cts_enable_byte = 1;
- }
- dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
+ dbg("set_baud_rate: send second control message, data = %02X",
+ cts_enable_byte);
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_CTS_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
- WDR_TIMEOUT);
+ MCT_U232_SET_CTS_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
- MCT_U232_SET_CTS_REQUEST, rc);
+ err("Sending USB device request code %d failed (error = %d)",
+ MCT_U232_SET_CTS_REQUEST, rc);
- return rc;
+ return rc;
} /* mct_u232_set_baud_rate */
static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
{
- int rc;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_LINE_CTRL_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_LINE_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
dbg("set_line_ctrl: 0x%x", lcr);
- return rc;
+ return rc;
} /* mct_u232_set_line_ctrl */
static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
unsigned int control_state)
{
- int rc;
+ int rc;
unsigned char mcr = MCT_U232_MCR_NONE;
if (control_state & TIOCM_DTR)
@@ -314,37 +319,39 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
if (control_state & TIOCM_RTS)
mcr |= MCT_U232_MCR_RTS;
- rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_MODEM_CTRL_REQUEST,
- MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
- WDR_TIMEOUT);
+ rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ MCT_U232_SET_MODEM_CTRL_REQUEST,
+ MCT_U232_SET_REQUEST_TYPE,
+ 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+ WDR_TIMEOUT);
if (rc < 0)
err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
- return rc;
+ return rc;
} /* mct_u232_set_modem_ctrl */
-static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
+static int mct_u232_get_modem_stat(struct usb_serial *serial,
+ unsigned char *msr)
{
- int rc;
- rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- MCT_U232_GET_MODEM_STAT_REQUEST,
- MCT_U232_GET_REQUEST_TYPE,
- 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
- WDR_TIMEOUT);
+ int rc;
+ rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCT_U232_GET_MODEM_STAT_REQUEST,
+ MCT_U232_GET_REQUEST_TYPE,
+ 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+ WDR_TIMEOUT);
if (rc < 0) {
err("Get MODEM STATus failed (error = %d)", rc);
*msr = 0;
}
dbg("get_modem_stat: 0x%x", *msr);
- return rc;
+ return rc;
} /* mct_u232_get_modem_stat */
-static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
+static void mct_u232_msr_to_state(unsigned int *control_state,
+ unsigned char msr)
{
- /* Translate Control Line states */
+ /* Translate Control Line states */
if (msr & MCT_U232_MSR_DSR)
*control_state |= TIOCM_DSR;
else
@@ -361,14 +368,14 @@ static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr
*control_state |= TIOCM_CD;
else
*control_state &= ~TIOCM_CD;
- dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
+ dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
} /* mct_u232_msr_to_state */
/*
* Driver's tty interface functions
*/
-static int mct_u232_startup (struct usb_serial *serial)
+static int mct_u232_startup(struct usb_serial *serial)
{
struct mct_u232_private *priv;
struct usb_serial_port *port, *rport;
@@ -390,18 +397,18 @@ static int mct_u232_startup (struct usb_serial *serial)
rport->interrupt_in_urb = NULL;
port->read_urb->context = port;
- return (0);
+ return 0;
} /* mct_u232_startup */
-static void mct_u232_shutdown (struct usb_serial *serial)
+static void mct_u232_shutdown(struct usb_serial *serial)
{
struct mct_u232_private *priv;
int i;
-
+
dbg("%s", __func__);
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
if (priv) {
@@ -411,7 +418,8 @@ static void mct_u232_shutdown (struct usb_serial *serial)
}
} /* mct_u232_shutdown */
-static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
+static int mct_u232_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -428,21 +436,22 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
* it seems to be able to accept only 16 bytes (and that's what
* SniffUSB says too...)
*/
- if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
+ if (le16_to_cpu(serial->dev->descriptor.idProduct)
+ == MCT_U232_SITECOM_PID)
port->bulk_out_size = 16;
- /* Do a defined restart: the normal serial device seems to
+ /* Do a defined restart: the normal serial device seems to
* always turn on DTR and RTS here, so do the same. I'm not
* sure if this is really necessary. But it should not harm
* either.
*/
spin_lock_irqsave(&priv->lock, flags);
- if (port->tty->termios->c_cflag & CBAUD)
+ if (tty && (tty->termios->c_cflag & CBAUD))
priv->control_state = TIOCM_DTR | TIOCM_RTS;
else
priv->control_state = 0;
-
- priv->last_lcr = (MCT_U232_DATA_BITS_8 |
+
+ priv->last_lcr = (MCT_U232_DATA_BITS_8 |
MCT_U232_PARITY_NONE |
MCT_U232_STOP_BITS_1);
control_state = priv->control_state;
@@ -481,15 +490,16 @@ error:
} /* mct_u232_open */
-static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+static void mct_u232_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
unsigned int c_cflag;
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
dbg("%s port %d", __func__, port->number);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
mutex_lock(&port->serial->disc_mutex);
if (c_cflag & HUPCL && !port->serial->disconnected) {
/* drop DTR and RTS */
@@ -512,7 +522,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
} /* mct_u232_close */
-static void mct_u232_read_int_callback (struct urb *urb)
+static void mct_u232_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -545,36 +555,34 @@ static void mct_u232_read_int_callback (struct urb *urb)
return;
}
- dbg("%s - port %d", __func__, port->number);
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ dbg("%s - port %d", __func__, port->number);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
/*
* Work-a-round: handle the 'usual' bulk-in pipe here
*/
if (urb->transfer_buffer_length > 2) {
- int i;
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
goto exit;
}
-
+
/*
* The interrupt-in pipe signals exceptional conditions (modem line
* signal changes and errors). data[0] holds MSR, data[1] holds LSR.
*/
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[MCT_U232_MSR_INDEX];
-
+
/* Record Control Line states */
mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
#if 0
- /* Not yet handled. See belin_sa.c for further information */
+ /* Not yet handled. See belkin_sa.c for further information */
/* Now to report any errors */
priv->last_lsr = data[MCT_U232_LSR_INDEX];
/*
@@ -583,7 +591,7 @@ static void mct_u232_read_int_callback (struct urb *urb)
* to look in to this before committing any code.
*/
if (priv->last_lsr & MCT_U232_LSR_ERR) {
- tty = port->tty;
+ tty = port->port.tty;
/* Overrun Error */
if (priv->last_lsr & MCT_U232_LSR_OE) {
}
@@ -600,18 +608,19 @@ static void mct_u232_read_int_callback (struct urb *urb)
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
- retval = usb_submit_urb (urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
- err ("%s - usb_submit_urb failed with result %d",
+ err("%s - usb_submit_urb failed with result %d",
__func__, retval);
} /* mct_u232_read_int_callback */
-static void mct_u232_set_termios (struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void mct_u232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- struct ktermios *termios = port->tty->termios;
+ struct ktermios *termios = tty->termios;
unsigned int cflag = termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
@@ -631,20 +640,20 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
* Premature optimization is the root of all evil.
*/
- /* reassert DTR and RTS on transition from B0 */
+ /* reassert DTR and RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
dbg("%s: baud was B0", __func__);
control_state |= TIOCM_DTR | TIOCM_RTS;
mct_u232_set_modem_ctrl(serial, control_state);
}
- mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
+ mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
- if ((cflag & CBAUD) == B0 ) {
+ if ((cflag & CBAUD) == B0) {
dbg("%s: baud is B0", __func__);
/* Drop RTS and DTR */
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(serial, control_state);
}
/*
@@ -689,8 +698,9 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
} /* mct_u232_set_termios */
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned char lcr;
@@ -709,12 +719,13 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
-static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
+static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -724,14 +735,15 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
return control_state;
}
-static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int control_state;
unsigned long flags;
-
+
dbg("%s", __func__);
spin_lock_irqsave(&priv->lock, flags);
@@ -751,77 +763,50 @@ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
return mct_u232_set_modem_ctrl(serial, control_state);
}
-static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- dbg("%scmd=0x%x", __func__, cmd);
-
- /* Based on code from acm.c and others */
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- return( 0 );
-
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- return 0;
-
- default:
- dbg("%s: arg not supported - 0x%04x", __func__,cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* mct_u232_ioctl */
-
-static void mct_u232_throttle (struct usb_serial_port *port)
+static void mct_u232_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state;
- struct tty_struct *tty;
- tty = port->tty;
dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
priv->rx_flags |= THROTTLED;
if (C_CRTSCTS(tty)) {
- priv->control_state &= ~TIOCM_RTS;
- control_state = priv->control_state;
- spin_unlock_irqrestore(&priv->lock, flags);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ priv->control_state &= ~TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else {
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
}
-static void mct_u232_unthrottle (struct usb_serial_port *port)
+static void mct_u232_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state;
- struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
- tty = port->tty;
spin_lock_irqsave(&priv->lock, flags);
if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
- priv->rx_flags &= ~THROTTLED;
- priv->control_state |= TIOCM_RTS;
- control_state = priv->control_state;
- spin_unlock_irqrestore(&priv->lock, flags);
- (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ priv->rx_flags &= ~THROTTLED;
+ priv->control_state |= TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else {
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
}
-static int __init mct_u232_init (void)
+static int __init mct_u232_init(void)
{
int retval;
retval = usb_serial_register(&mct_u232_device);
@@ -839,18 +824,17 @@ failed_usb_serial_register:
}
-static void __exit mct_u232_exit (void)
+static void __exit mct_u232_exit(void)
{
- usb_deregister (&mct_u232_driver);
- usb_serial_deregister (&mct_u232_device);
+ usb_deregister(&mct_u232_driver);
+ usb_serial_deregister(&mct_u232_device);
}
-
-module_init (mct_u232_init);
+module_init(mct_u232_init);
module_exit(mct_u232_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 50f1fe26333..7c4917d77c0 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -33,7 +33,7 @@
#include <linux/serial_reg.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
@@ -64,8 +64,7 @@
#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */
/* This structure holds all of the local port information */
-struct moschip_port
-{
+struct moschip_port {
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
__u8 shadowMSR; /* last MSR value received */
@@ -76,8 +75,7 @@ struct moschip_port
};
/* This structure holds all of the individual serial device information */
-struct moschip_serial
-{
+struct moschip_serial {
int interrupt_started;
};
@@ -88,7 +86,7 @@ static int debug;
#define MOSCHIP_DEVICE_ID_7715 0x7715
static struct usb_device_id moschip_port_id_table [] = {
- { USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) },
+ { USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
{ } /* terminating entry */
};
MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
@@ -108,7 +106,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
__u8 sp1;
__u8 sp2;
- dbg("%s"," : Entering\n");
+ dbg("%s", " : Entering\n");
switch (status) {
case 0:
@@ -208,7 +206,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
mos7720_port = urb->context;
if (!mos7720_port) {
- dbg("%s","NULL mos7720_port pointer \n");
+ dbg("%s", "NULL mos7720_port pointer \n");
return ;
}
@@ -218,7 +216,7 @@ static void mos7720_bulk_in_callback(struct urb *urb)
data = urb->transfer_buffer;
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -264,7 +262,7 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
dbg("Entering .........");
- tty = mos7720_port->port->tty;
+ tty = mos7720_port->port->port.tty;
if (tty && mos7720_port->open)
tty_wakeup(tty);
@@ -284,17 +282,16 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
__u16 size = 0x0000;
if (value < MOS_MAX_PORT) {
- if (product == MOSCHIP_DEVICE_ID_7715) {
+ if (product == MOSCHIP_DEVICE_ID_7715)
value = value*0x100+0x100;
- } else {
+ else
value = value*0x100+0x200;
- }
} else {
value = 0x0000;
if ((product == MOSCHIP_DEVICE_ID_7715) &&
(index != 0x08)) {
dbg("serial->product== MOSCHIP_DEVICE_ID_7715");
- //index = 0x01 ;
+ /* index = 0x01 ; */
}
}
@@ -308,19 +305,20 @@ static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
request = (__u8)MOS_READ;
requesttype = (__u8)0xC0;
size = 0x01;
- pipe = usb_rcvctrlpipe(serial->dev,0);
+ pipe = usb_rcvctrlpipe(serial->dev, 0);
}
status = usb_control_msg(serial->dev, pipe, request, requesttype,
value, index, data, size, MOS_WDR_TIMEOUT);
if (status < 0)
- dbg("Command Write failed Value %x index %x\n",value,index);
+ dbg("Command Write failed Value %x index %x\n", value, index);
return status;
}
-static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+static int mos7720_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port0;
@@ -351,7 +349,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* Initialising the write urb pool */
for (j = 0; j < NUM_URBS; ++j) {
- urb = usb_alloc_urb(0,GFP_KERNEL);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
mos7720_port->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -385,7 +383,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
*/
port_number = port->number - port->serial->minor;
send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
- dbg("SS::%p LSR:%x\n",mos7720_port, data);
+ dbg("SS::%p LSR:%x\n", mos7720_port, data);
dbg("Check:Sending Command ..........");
@@ -402,10 +400,10 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
data = 0xCF;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
data = 0x03;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x0b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -420,7 +418,8 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
data = 0x03;
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
data = 0x00;
- send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
+ send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT,
+ port_number + 1, &data);
*/
data = 0x00;
send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -429,28 +428,26 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
data = 0x83;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
data = 0x00;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = 0x03;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
-//Matrix
-
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* see if we've set up our endpoint info yet *
* (can't set it up in mos7720_startup as the *
@@ -465,15 +462,15 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* set up our interrupt urb */
usb_fill_int_urb(port0->interrupt_in_urb, serial->dev,
- usb_rcvintpipe(serial->dev,
- port->interrupt_in_endpointAddress),
- port0->interrupt_in_buffer,
- port0->interrupt_in_urb->transfer_buffer_length,
- mos7720_interrupt_callback, mos7720_port,
- port0->interrupt_in_urb->interval);
+ usb_rcvintpipe(serial->dev,
+ port->interrupt_in_endpointAddress),
+ port0->interrupt_in_buffer,
+ port0->interrupt_in_urb->transfer_buffer_length,
+ mos7720_interrupt_callback, mos7720_port,
+ port0->interrupt_in_urb->interval);
/* start interrupt read for this mos7720 this interrupt *
- * will continue as long as the mos7720 is connected */
+ * will continue as long as the mos7720 is connected */
dbg("Submit URB over !!!");
response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
if (response)
@@ -485,14 +482,14 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* set up our bulk in urb */
usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
+ port->bulk_in_endpointAddress),
port->bulk_in_buffer,
port->read_urb->transfer_buffer_length,
mos7720_bulk_in_callback, mos7720_port);
response = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (response)
- dev_err(&port->dev,
- "%s - Error %d submitting read urb\n", __func__, response);
+ dev_err(&port->dev, "%s - Error %d submitting read urb\n",
+ __func__, response);
/* initialize our icount structure */
memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
@@ -515,8 +512,9 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
* system,
* Otherwise we return a negative error number.
*/
-static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+static int mos7720_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int chars = 0;
struct moschip_port *mos7720_port;
@@ -530,14 +528,16 @@ static int mos7720_chars_in_buffer(struct usb_serial_port *port)
}
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
chars += URB_TRANSFER_BUFFER_SIZE;
}
dbg("%s - returns %d", __func__, chars);
return chars;
}
-static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct moschip_port *mos7720_port;
@@ -575,12 +575,12 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
* been disconnected */
if (!serial->disconnected) {
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x04, &data);
+ send_mos_cmd(serial, MOS_WRITE,
+ port->number - port->serial->minor, 0x04, &data);
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE,
+ port->number - port->serial->minor, 0x01, &data);
}
mutex_unlock(&serial->disc_mutex);
mos7720_port->open = 0;
@@ -588,9 +588,10 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
dbg("Leaving %s", __func__);
}
-static void mos7720_break(struct usb_serial_port *port, int break_state)
+static void mos7720_break(struct tty_struct *tty, int break_state)
{
- unsigned char data;
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned char data;
struct usb_serial *serial;
struct moschip_port *mos7720_port;
@@ -621,8 +622,9 @@ static void mos7720_break(struct usb_serial_port *port, int break_state)
* If successful, we return the amount of room that we have for this port
* Otherwise we return a negative error number.
*/
-static int mos7720_write_room(struct usb_serial_port *port)
+static int mos7720_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
int room = 0;
int i;
@@ -637,7 +639,8 @@ static int mos7720_write_room(struct usb_serial_port *port)
/* FIXME: Locking */
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
room += URB_TRANSFER_BUFFER_SIZE;
}
@@ -645,8 +648,8 @@ static int mos7720_write_room(struct usb_serial_port *port)
return room;
}
-static int mos7720_write(struct usb_serial_port *port,
- const unsigned char *data, int count)
+static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
int status;
int i;
@@ -672,9 +675,10 @@ static int mos7720_write(struct usb_serial_port *port,
urb = NULL;
for (i = 0; i < NUM_URBS; ++i) {
- if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
+ if (mos7720_port->write_urb_pool[i] &&
+ mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
urb = mos7720_port->write_urb_pool[i];
- dbg("URB:%d",i);
+ dbg("URB:%d", i);
break;
}
}
@@ -692,7 +696,7 @@ static int mos7720_write(struct usb_serial_port *port,
goto exit;
}
}
- transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
memcpy(urb->transfer_buffer, current_position, transfer_size);
usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
@@ -701,12 +705,12 @@ static int mos7720_write(struct usb_serial_port *port,
/* fill urb with data and submit */
usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
+ port->bulk_out_endpointAddress),
urb->transfer_buffer, transfer_size,
mos7720_bulk_out_data_callback, mos7720_port);
/* send it down the pipe */
- status = usb_submit_urb(urb,GFP_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err("%s - usb_submit_urb(write bulk) failed with status = %d",
__func__, status);
@@ -719,10 +723,10 @@ exit:
return bytes_sent;
}
-static void mos7720_throttle(struct usb_serial_port *port)
+static void mos7720_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
int status;
dbg("%s- port %d\n", __func__, port->number);
@@ -739,16 +743,10 @@ static void mos7720_throttle(struct usb_serial_port *port)
dbg("%s: Entering ..........", __func__);
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = mos7720_write(port, &stop_char, 1);
+ status = mos7720_write(tty, port, &stop_char, 1);
if (status <= 0)
return;
}
@@ -764,11 +762,11 @@ static void mos7720_throttle(struct usb_serial_port *port)
}
}
-static void mos7720_unthrottle(struct usb_serial_port *port)
+static void mos7720_unthrottle(struct tty_struct *tty)
{
- struct tty_struct *tty;
- int status;
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+ int status;
if (mos7720_port == NULL)
return;
@@ -780,16 +778,10 @@ static void mos7720_unthrottle(struct usb_serial_port *port)
dbg("%s: Entering ..........", __func__);
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = mos7720_write(port, &start_char, 1);
+ status = mos7720_write(tty, port, &start_char, 1);
if (status <= 0)
return;
}
@@ -819,9 +811,9 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
port = mos7720_port->port;
serial = port->serial;
- /***********************************************
- * Init Sequence for higher rates
- ***********************************************/
+ /***********************************************
+ * Init Sequence for higher rates
+ ***********************************************/
dbg("Sending Setting Commands ..........");
port_number = port->number - port->serial->minor;
@@ -832,7 +824,7 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
data = 0x0CF;
send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data);
data = 0x00b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x00b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -843,12 +835,12 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
- /***********************************************
- * Set for higher rates *
- ***********************************************/
+ /***********************************************
+ * Set for higher rates *
+ ***********************************************/
data = baud * 0x10;
- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);
+ send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
data = 0x003;
send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -856,34 +848,33 @@ static int set_higher_rates(struct moschip_port *mos7720_port,
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
data = 0x02b;
- mos7720_port->shadowMCR = data;
+ mos7720_port->shadowMCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
data = 0x02b;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
- /***********************************************
- * Set DLL/DLM
- ***********************************************/
+ /***********************************************
+ * Set DLL/DLM
+ ***********************************************/
data = mos7720_port->shadowLCR | UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
data = 0x001; /* DLL */
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
data = 0x000; /* DLM */
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
+ mos7720_port->shadowLCR = data;
send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
return 0;
}
/* baud rate information */
-struct divisor_table_entry
-{
+struct divisor_table_entry {
__u32 baudrate;
__u16 divisor;
};
@@ -932,8 +923,8 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
}
}
- /* After trying for all the standard baud rates *
- * Try calculating the divisor for this baud rate */
+ /* After trying for all the standard baud rates *
+ * Try calculating the divisor for this baud rate */
if (baudrate > 75 && baudrate < 230400) {
/* get the divisor */
custom = (__u16)(230400L / baudrate);
@@ -945,7 +936,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor)
custom++;
*divisor = custom;
- dbg("Baud %d = %d",baudrate, custom);
+ dbg("Baud %d = %d", baudrate, custom);
return 0;
}
@@ -979,29 +970,29 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
number = port->number - port->serial->minor;
dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
- /* Calculate the Divisor */
+ /* Calculate the Divisor */
status = calc_baud_rate_divisor(baudrate, &divisor);
if (status) {
err("%s - bad baud rate", __func__);
return status;
}
- /* Enable access to divisor latch */
- data = mos7720_port->shadowLCR | UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
- send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
+ /* Enable access to divisor latch */
+ data = mos7720_port->shadowLCR | UART_LCR_DLAB;
+ mos7720_port->shadowLCR = data;
+ send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
/* Write the divisor */
data = ((unsigned char)(divisor & 0xff));
- send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
+ send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
data = ((unsigned char)((divisor & 0xff00) >> 8));
- send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
+ send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
- /* Disable access to divisor latch */
- data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
- mos7720_port->shadowLCR = data;
- send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
+ /* Disable access to divisor latch */
+ data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
+ mos7720_port->shadowLCR = data;
+ send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
return status;
}
@@ -1011,12 +1002,12 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
* This routine is called to set the UART on the device to match
* the specified new settings.
*/
-static void change_port_settings(struct moschip_port *mos7720_port,
+static void change_port_settings(struct tty_struct *tty,
+ struct moschip_port *mos7720_port,
struct ktermios *old_termios)
{
struct usb_serial_port *port;
struct usb_serial *serial;
- struct tty_struct *tty;
int baud;
unsigned cflag;
unsigned iflag;
@@ -1042,8 +1033,6 @@ static void change_port_settings(struct moschip_port *mos7720_port,
return;
}
- tty = mos7720_port->port->tty;
-
dbg("%s: Entering ..........", __func__);
lData = UART_LCR_WLEN8;
@@ -1106,29 +1095,31 @@ static void change_port_settings(struct moschip_port *mos7720_port,
#define LCR_PAR_MASK 0x38 /* Mask for parity field */
/* Update the LCR with the correct value */
- mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+ mos7720_port->shadowLCR &=
+ ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
mos7720_port->shadowLCR |= (lData | lParity | lStop);
/* Disable Interrupts */
data = 0x00;
- send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);
+ send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+ UART_IER, &data);
data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
data = 0xcf;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
/* Send the updated LCR value to the mos7720 */
data = mos7720_port->shadowLCR;
- send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
+ send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
- data = 0x00b;
- mos7720_port->shadowMCR = data;
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
- data = 0x00b;
- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+ data = 0x00b;
+ mos7720_port->shadowMCR = data;
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+ data = 0x00b;
+ send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
/* set up the MCR register and send it to the mos7720 */
mos7720_port->shadowMCR = UART_MCR_OUT2;
@@ -1137,9 +1128,8 @@ static void change_port_settings(struct moschip_port *mos7720_port,
if (cflag & CRTSCTS) {
mos7720_port->shadowMCR |= (UART_MCR_XONANY);
-
- /* To set hardware flow control to the specified *
- * serial port, in SP1/2_CONTROL_REG */
+ /* To set hardware flow control to the specified *
+ * serial port, in SP1/2_CONTROL_REG */
if (port->number) {
data = 0x001;
send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
@@ -1198,14 +1188,13 @@ static void change_port_settings(struct moschip_port *mos7720_port,
* this function is called by the tty driver when it wants to change the
* termios structure.
*/
-static void mos7720_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void mos7720_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
int status;
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7720_port;
- struct tty_struct *tty;
serial = port->serial;
@@ -1214,15 +1203,12 @@ static void mos7720_set_termios(struct usb_serial_port *port,
if (mos7720_port == NULL)
return;
- tty = port->tty;
-
-
if (!mos7720_port->open) {
dbg("%s - port not opened", __func__);
return;
}
- dbg("%s\n","setting termios - ASPIRE");
+ dbg("%s\n", "setting termios - ASPIRE");
cflag = tty->termios->c_cflag;
@@ -1237,14 +1223,14 @@ static void mos7720_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
/* change the port settings to the new ones specified */
- change_port_settings(mos7720_port, old_termios);
+ change_port_settings(tty, mos7720_port, old_termios);
- if(!port->read_urb) {
- dbg("%s","URB KILLED !!!!!\n");
+ if (!port->read_urb) {
+ dbg("%s", "URB KILLED !!!!!\n");
return;
}
- if(port->read_urb->status != -EINPROGRESS) {
+ if (port->read_urb->status != -EINPROGRESS) {
port->read_urb->dev = serial->dev;
status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (status)
@@ -1264,13 +1250,13 @@ static void mos7720_set_termios(struct usb_serial_port *port,
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct moschip_port *mos7720_port,
- unsigned int __user *value)
+static int get_lsr_info(struct tty_struct *tty,
+ struct moschip_port *mos7720_port, unsigned int __user *value)
{
int count;
unsigned int result = 0;
- count = mos7720_chars_in_buffer(mos7720_port->port);
+ count = mos7720_chars_in_buffer(tty);
if (count == 0) {
dbg("%s -- Empty", __func__);
result = TIOCSER_TEMT;
@@ -1290,7 +1276,7 @@ static int get_number_bytes_avail(struct moschip_port *mos7720_port,
unsigned int __user *value)
{
unsigned int result = 0;
- struct tty_struct *tty = mos7720_port->port->tty;
+ struct tty_struct *tty = mos7720_port->port->port.tty;
if (!tty)
return -ENOIOCTLCMD;
@@ -1316,7 +1302,7 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
if (mos7720_port == NULL)
return -1;
- port = (struct usb_serial_port*)mos7720_port->port;
+ port = (struct usb_serial_port *)mos7720_port->port;
mcr = mos7720_port->shadowMCR;
if (copy_from_user(&arg, value, sizeof(int)))
@@ -1397,7 +1383,7 @@ static int get_serial_info(struct moschip_port *mos7720_port,
tmp.port = mos7720_port->port->number;
tmp.irq = 0;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+ tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
tmp.baud_base = 9600;
tmp.close_delay = 5*HZ;
tmp.closing_wait = 30*HZ;
@@ -1407,9 +1393,10 @@ static int get_serial_info(struct moschip_port *mos7720_port,
return 0;
}
-static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port;
struct async_icount cnow;
struct async_icount cprev;
@@ -1431,14 +1418,16 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+ return get_lsr_info(tty, mos7720_port,
+ (unsigned int __user *)arg);
return 0;
+ /* FIXME: These should be using the mode methods */
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
- dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
- port->number);
+ dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET",
+ __func__, port->number);
return set_modem_info(mos7720_port, cmd,
(unsigned int __user *)arg);
@@ -1452,10 +1441,6 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
return get_serial_info(mos7720_port,
(struct serial_struct __user *)arg);
- case TIOCSSERIAL:
- dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
- break;
-
case TIOCMIWAIT:
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
cprev = mos7720_port->icount;
@@ -1469,7 +1454,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
return 0;
}
cprev = cnow;
@@ -1492,7 +1477,7 @@ static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
icount.buf_overrun = cnow.buf_overrun;
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
- port->number, icount.rx, icount.tx );
+ port->number, icount.rx, icount.tx);
if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
return -EFAULT;
return 0;
@@ -1543,7 +1528,8 @@ static int mos7720_startup(struct usb_serial *serial)
/* Initialize all port interrupt end point to port 0 int
* endpoint. Our device has only one interrupt endpoint
* comman to all ports */
- serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
+ serial->port[i]->interrupt_in_endpointAddress =
+ serial->port[0]->interrupt_in_endpointAddress;
mos7720_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], mos7720_port);
@@ -1555,13 +1541,15 @@ static int mos7720_startup(struct usb_serial *serial)
/* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);
+ (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
- send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data); // LSR For Port 1
- dbg("LSR:%x",data);
+ /* LSR For Port 1 */
+ send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data);
+ dbg("LSR:%x", data);
- send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data); // LSR For Port 2
- dbg("LSR:%x",data);
+ /* LSR For Port 2 */
+ send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data);
+ dbg("LSR:%x", data);
return 0;
}
@@ -1571,7 +1559,7 @@ static void mos7720_shutdown(struct usb_serial *serial)
int i;
/* free private structure allocated for serial port */
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
@@ -1651,8 +1639,8 @@ module_init(moschip7720_init);
module_exit(moschip7720_exit);
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 78f2f6db494..09d82062b97 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -33,7 +33,7 @@
#include <linux/serial.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
/*
* Version Information
@@ -82,8 +82,8 @@
* Defines used for sending commands to port
*/
-#define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever */
-#define MOS_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */
+#define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */
#define MOS_PORT1 0x0200
#define MOS_PORT2 0x0300
@@ -102,8 +102,8 @@
#define MAX_NAME_LEN 64
-#define ZLP_REG1 0x3A //Zero_Flag_Reg1 58
-#define ZLP_REG5 0x3E //Zero_Flag_Reg5 62
+#define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */
+#define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */
/* For higher baud Rates use TIOCEXBAUD */
#define TIOCEXBAUD 0x5462
@@ -142,7 +142,7 @@
#define MOS_MSR_DELTA_RI 0x40
#define MOS_MSR_DELTA_CD 0x80
-// Serial Port register Address
+/* Serial Port register Address */
#define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01))
#define FIFO_CONTROL_REGISTER ((__u16)(0x02))
#define LINE_CONTROL_REGISTER ((__u16)(0x03))
@@ -201,11 +201,11 @@ struct moschip_port {
struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
- /*Offsets */
+ /* Offsets */
__u8 SpRegOffset;
__u8 ControlRegOffset;
__u8 DcrRegOffset;
- //for processing control URBS in interrupt context
+ /* for processing control URBS in interrupt context */
struct urb *control_urb;
struct usb_ctrlrequest *dr;
char *ctrl_buf;
@@ -244,7 +244,7 @@ static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
*/
static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = port->serial->dev;
int ret = 0;
@@ -269,16 +269,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
struct usb_device *dev = port->serial->dev;
val = val & 0x00ff;
- // For the UART control registers, the application number need to be Or'ed
+ /* For the UART control registers, the application number need
+ to be Or'ed */
if (port->serial->num_ports == 4) {
- val |=
- (((__u16) port->number - (__u16) (port->serial->minor)) +
- 1) << 8;
+ val |= (((__u16) port->number -
+ (__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_set_uart_reg application number is %x\n", val);
} else {
if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- val |=
- (((__u16) port->number -
+ val |= (((__u16) port->number -
(__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_set_uart_reg application number is %x\n",
val);
@@ -302,14 +301,15 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
* by passing usb_rcvctrlpipe function as parameter.
*/
static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = port->serial->dev;
int ret = 0;
__u16 Wval;
- //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
- /*Wval is same as application number */
+ /* dbg("application number is %4x \n",
+ (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
+ /* Wval is same as application number */
if (port->serial->num_ports == 4) {
Wval =
(((__u16) port->number - (__u16) (port->serial->minor)) +
@@ -317,14 +317,12 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
dbg("mos7840_get_uart_reg application number is %x\n", Wval);
} else {
if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
- Wval =
- (((__u16) port->number -
+ Wval = (((__u16) port->number -
(__u16) (port->serial->minor)) + 1) << 8;
dbg("mos7840_get_uart_reg application number is %x\n",
Wval);
} else {
- Wval =
- (((__u16) port->number -
+ Wval = (((__u16) port->number -
(__u16) (port->serial->minor)) + 2) << 8;
dbg("mos7840_get_uart_reg application number is %x\n",
Wval);
@@ -406,11 +404,11 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
dbg("%s - %02x", __func__, new_lsr);
if (new_lsr & SERIAL_LSR_BI) {
- //
- // Parity and Framing errors only count if they
- // occur exclusive of a break being
- // received.
- //
+ /*
+ * Parity and Framing errors only count if they
+ * occur exclusive of a break being
+ * received.
+ */
new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
}
@@ -492,7 +490,7 @@ exit:
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
- __u16 * val)
+ __u16 *val)
{
struct usb_device *dev = mcs->port->serial->dev;
struct usb_ctrlrequest *dr = mcs->dr;
@@ -501,7 +499,7 @@ static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
dr->bRequestType = MCS_RD_RTYPE;
dr->bRequest = MCS_RDREQ;
- dr->wValue = cpu_to_le16(Wval); //0;
+ dr->wValue = cpu_to_le16(Wval); /* 0 */
dr->wIndex = cpu_to_le16(reg);
dr->wLength = cpu_to_le16(2);
@@ -607,7 +605,8 @@ static void mos7840_interrupt_callback(struct urb *urb)
}
}
}
- if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
+ if (!(rv < 0))
+ /* the completion handler for the control urb will resubmit */
return;
exit:
result = usb_submit_urb(urb, GFP_ATOMIC);
@@ -656,8 +655,8 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
if (!port ||
mos7840_port_paranoia_check(port, function) ||
mos7840_serial_paranoia_check(port->serial, function)) {
- /* then say that we don't have a valid usb_serial thing, which will
- * end up genrating -ENODEV return values */
+ /* then say that we don't have a valid usb_serial thing,
+ * which will end up genrating -ENODEV return values */
return NULL;
}
@@ -710,7 +709,7 @@ static void mos7840_bulk_in_callback(struct urb *urb)
dbg("%s", "Entering ........... \n");
if (urb->actual_length) {
- tty = mos7840_port->port->tty;
+ tty = mos7840_port->port->port.tty;
if (tty) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -741,8 +740,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
/*****************************************************************************
* mos7840_bulk_out_data_callback
- * this is the callback function for when we have finished sending serial data
- * on the bulk out endpoint.
+ * this is the callback function for when we have finished sending
+ * serial data on the bulk out endpoint.
*****************************************************************************/
static void mos7840_bulk_out_data_callback(struct urb *urb)
@@ -774,7 +773,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
dbg("%s \n", "Entering .........");
- tty = mos7840_port->port->tty;
+ tty = mos7840_port->port->port.tty;
if (tty && mos7840_port->open)
tty_wakeup(tty);
@@ -804,7 +803,8 @@ static int mos7840_serial_probe(struct usb_serial *serial,
* Otherwise we return a negative error number.
*****************************************************************************/
-static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+static int mos7840_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int response;
int j;
@@ -847,7 +847,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
continue;
}
- urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_KERNEL);
if (!urb->transfer_buffer) {
usb_free_urb(urb);
mos7840_port->write_urb_pool[j] = NULL;
@@ -868,9 +869,8 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
* 0x08 : SP1/2 Control Reg
*****************************************************************************/
-//NEED to check the following Block
+ /* NEED to check the following Block */
- status = 0;
Data = 0x0;
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
if (status < 0) {
@@ -890,36 +890,35 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
dbg("writing Spreg failed\n");
return -1;
}
-//End of block to be checked
+ /* End of block to be checked */
- status = 0;
Data = 0x0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
if (status < 0) {
dbg("Reading Controlreg failed\n");
return -1;
}
- Data |= 0x08; //Driver done bit
- Data |= 0x20; //rx_disable
- status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ Data |= 0x08; /* Driver done bit */
+ Data |= 0x20; /* rx_disable */
+ status = mos7840_set_reg_sync(port,
+ mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dbg("writing Controlreg failed\n");
return -1;
}
- //do register settings here
- // Set all regs to the device default values.
- ////////////////////////////////////
- // First Disable all interrupts.
- ////////////////////////////////////
-
+ /* do register settings here */
+ /* Set all regs to the device default values. */
+ /***********************************
+ * First Disable all interrupts.
+ ***********************************/
Data = 0x00;
status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
if (status < 0) {
dbg("disableing interrupts failed\n");
return -1;
}
- // Set FIFO_CONTROL_REGISTER to the default value
+ /* Set FIFO_CONTROL_REGISTER to the default value */
Data = 0x00;
status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
if (status < 0) {
@@ -946,90 +945,73 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
mos7840_port->shadowLCR = Data;
- Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
+ Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
Data = 0x0c;
- status = 0;
status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
Data = 0x0;
- status = 0;
status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
Data = Data & ~SERIAL_LCR_DLAB;
- status = 0;
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
mos7840_port->shadowLCR = Data;
- //clearing Bulkin and Bulkout Fifo
+ /* clearing Bulkin and Bulkout Fifo */
Data = 0x0;
- status = 0;
status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
Data = Data | 0x0c;
- status = 0;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
Data = Data & ~0x0c;
- status = 0;
status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
- //Finally enable all interrupts
- Data = 0x0;
+ /* Finally enable all interrupts */
Data = 0x0c;
- status = 0;
status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
- //clearing rx_disable
+ /* clearing rx_disable */
Data = 0x0;
- status = 0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
Data = Data & ~0x20;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
+ Data);
- // rx_negate
+ /* rx_negate */
Data = 0x0;
- status = 0;
- status =
- mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset,
+ &Data);
Data = Data | 0x10;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
+ Data);
/* force low_latency on so that our tty_push actually forces *
* the data through,otherwise it is scheduled, and with *
* high data rates (like with OHCI) data can get lost. */
+ if (tty)
+ tty->low_latency = 1;
- if (port->tty)
- port->tty->low_latency = 1;
-/* Check to see if we've set up our endpoint info yet *
- * (can't set it up in mos7840_startup as the structures *
- * were not set up at that time.) */
+ /* Check to see if we've set up our endpoint info yet *
+ * (can't set it up in mos7840_startup as the structures *
+ * were not set up at that time.) */
if (port0->open_ports == 1) {
if (serial->port[0]->interrupt_in_buffer == NULL) {
-
/* set up interrupt urb */
-
usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
- serial->dev,
- usb_rcvintpipe(serial->dev,
- serial->port[0]->
- interrupt_in_endpointAddress),
- serial->port[0]->interrupt_in_buffer,
- serial->port[0]->interrupt_in_urb->
- transfer_buffer_length,
- mos7840_interrupt_callback,
- serial,
- serial->port[0]->interrupt_in_urb->
- interval);
+ serial->dev,
+ usb_rcvintpipe(serial->dev,
+ serial->port[0]->interrupt_in_endpointAddress),
+ serial->port[0]->interrupt_in_buffer,
+ serial->port[0]->interrupt_in_urb->
+ transfer_buffer_length,
+ mos7840_interrupt_callback,
+ serial,
+ serial->port[0]->interrupt_in_urb->interval);
/* start interrupt read for mos7840 *
* will continue as long as mos7840 is connected */
@@ -1084,14 +1066,16 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
/* initialize our port settings */
- mos7840_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */
+ /* Must set to enable ints! */
+ mos7840_port->shadowMCR = MCR_MASTER_IE;
/* send a open port command */
mos7840_port->open = 1;
- //mos7840_change_port_settings(mos7840_port,old_termios);
+ /* mos7840_change_port_settings(mos7840_port,old_termios); */
mos7840_port->icount.tx = 0;
mos7840_port->icount.rx = 0;
- dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", serial, mos7840_port, port);
+ dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n",
+ serial, mos7840_port, port);
return 0;
@@ -1104,11 +1088,12 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
* been written, but hasn't made it out the port yet)
* If successful, we return the number of bytes left to be written in the
* system,
- * Otherwise we return a negative error number.
+ * Otherwise we return zero.
*****************************************************************************/
-static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+static int mos7840_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int chars = 0;
unsigned long flags;
@@ -1118,22 +1103,20 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port \n");
- return -1;
+ return 0;
}
mos7840_port = mos7840_get_port_private(port);
if (mos7840_port == NULL) {
dbg("%s \n", "mos7840_break:leaving ...........");
- return -1;
+ return 0;
}
- spin_lock_irqsave(&mos7840_port->pool_lock,flags);
- for (i = 0; i < NUM_URBS; ++i) {
- if (mos7840_port->busy[i]) {
+ spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+ for (i = 0; i < NUM_URBS; ++i)
+ if (mos7840_port->busy[i])
chars += URB_TRANSFER_BUFFER_SIZE;
- }
- }
- spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+ spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
dbg("%s - returns %d", __func__, chars);
return chars;
@@ -1149,7 +1132,8 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
* 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
-static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+static void mos7840_block_until_tx_empty(struct tty_struct *tty,
+ struct moschip_port *mos7840_port)
{
int timeout = HZ / 10;
int wait = 30;
@@ -1157,12 +1141,11 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
while (1) {
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
/* Check for Buffer status */
- if (count <= 0) {
+ if (count <= 0)
return;
- }
/* Block the thread for a while */
interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1185,7 +1168,8 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
* this function is called by the tty driver when a port is closed
*****************************************************************************/
-static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+static void mos7840_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct moschip_port *mos7840_port;
@@ -1226,32 +1210,28 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
}
}
- if (serial->dev) {
+ if (serial->dev)
/* flush and block until tx is empty */
- mos7840_block_until_tx_empty(mos7840_port);
- }
+ mos7840_block_until_tx_empty(tty, mos7840_port);
/* While closing port, shutdown all bulk read, write *
* and interrupt read if they exists */
if (serial->dev) {
-
if (mos7840_port->write_urb) {
dbg("%s", "Shutdown bulk write\n");
usb_kill_urb(mos7840_port->write_urb);
}
-
if (mos7840_port->read_urb) {
dbg("%s", "Shutdown bulk read\n");
usb_kill_urb(mos7840_port->read_urb);
}
if ((&mos7840_port->control_urb)) {
dbg("%s", "Shutdown control read\n");
- // usb_kill_urb (mos7840_port->control_urb);
-
+ /*/ usb_kill_urb (mos7840_port->control_urb); */
}
}
-// if(mos7840_port->ctrl_buf != NULL)
-// kfree(mos7840_port->ctrl_buf);
+/* if(mos7840_port->ctrl_buf != NULL) */
+/* kfree(mos7840_port->ctrl_buf); */
port0->open_ports--;
dbg("mos7840_num_open_ports in close%d:in port%d\n",
port0->open_ports, port->number);
@@ -1264,10 +1244,8 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
if (mos7840_port->write_urb) {
/* if this urb had a transfer buffer already (old tx) free it */
-
- if (mos7840_port->write_urb->transfer_buffer != NULL) {
+ if (mos7840_port->write_urb->transfer_buffer != NULL)
kfree(mos7840_port->write_urb->transfer_buffer);
- }
usb_free_urb(mos7840_port->write_urb);
}
@@ -1293,20 +1271,19 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
*
************************************************************************/
-static void mos7840_block_until_chase_response(struct moschip_port
- *mos7840_port)
+static void mos7840_block_until_chase_response(struct tty_struct *tty,
+ struct moschip_port *mos7840_port)
{
int timeout = 1 * HZ;
int wait = 10;
int count;
while (1) {
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
/* Check for Buffer status */
- if (count <= 0) {
+ if (count <= 0)
return;
- }
/* Block the thread for a while */
interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1328,8 +1305,9 @@ static void mos7840_block_until_chase_response(struct moschip_port
* mos7840_break
* this function sends a break to the port
*****************************************************************************/
-static void mos7840_break(struct usb_serial_port *port, int break_state)
+static void mos7840_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned char data;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
@@ -1350,21 +1328,17 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL) {
+ if (mos7840_port == NULL)
return;
- }
-
- if (serial->dev) {
+ if (serial->dev)
/* flush and block until tx is empty */
- mos7840_block_until_chase_response(mos7840_port);
- }
+ mos7840_block_until_chase_response(tty, mos7840_port);
- if (break_state == -1) {
+ if (break_state == -1)
data = mos7840_port->shadowLCR | LCR_SET_BREAK;
- } else {
+ else
data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
- }
mos7840_port->shadowLCR = data;
dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
@@ -1383,8 +1357,9 @@ static void mos7840_break(struct usb_serial_port *port, int break_state)
* Otherwise we return a negative error number.
*****************************************************************************/
-static int mos7840_write_room(struct usb_serial_port *port)
+static int mos7840_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int i;
int room = 0;
unsigned long flags;
@@ -1406,9 +1381,8 @@ static int mos7840_write_room(struct usb_serial_port *port)
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
- if (!mos7840_port->busy[i]) {
+ if (!mos7840_port->busy[i])
room += URB_TRANSFER_BUFFER_SIZE;
- }
}
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
@@ -1426,7 +1400,7 @@ static int mos7840_write_room(struct usb_serial_port *port)
* return a negative error number.
*****************************************************************************/
-static int mos7840_write(struct usb_serial_port *port,
+static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count)
{
int status;
@@ -1438,45 +1412,41 @@ static int mos7840_write(struct usb_serial_port *port,
struct moschip_port *mos7840_port;
struct usb_serial *serial;
struct urb *urb;
- //__u16 Data;
+ /* __u16 Data; */
const unsigned char *current_position = data;
unsigned char *data1;
dbg("%s \n", "entering ...........");
- //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
+ /* dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+ mos7840_port->shadowLCR); */
#ifdef NOTMOS7840
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
mos7840_port->shadowLCR = Data;
dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
mos7840_port->shadowLCR);
- //Data = 0x03;
- //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
- //mos7840_port->shadowLCR=Data;//Need to add later
+ /* Data = 0x03; */
+ /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */
+ /* mos7840_port->shadowLCR=Data;//Need to add later */
- Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80
- status = 0;
+ Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
- //Data = 0x0c;
- //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
+ /* Data = 0x0c; */
+ /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */
Data = 0x00;
- status = 0;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
dbg("mos7840_write:DLL value is %x\n", Data);
Data = 0x0;
- status = 0;
status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
dbg("mos7840_write:DLM value is %x\n", Data);
Data = Data & ~SERIAL_LCR_DLAB;
dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
mos7840_port->shadowLCR);
- status = 0;
status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
#endif
@@ -1555,8 +1525,7 @@ static int mos7840_write(struct usb_serial_port *port,
mos7840_port->icount.tx += transfer_size;
smp_wmb();
dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
- exit:
-
+exit:
return bytes_sent;
}
@@ -1567,10 +1536,10 @@ static int mos7840_write(struct usb_serial_port *port,
* being read from the port.
*****************************************************************************/
-static void mos7840_throttle(struct usb_serial_port *port)
+static void mos7840_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
int status;
if (mos7840_port_paranoia_check(port, __func__)) {
@@ -1592,32 +1561,20 @@ static void mos7840_throttle(struct usb_serial_port *port)
dbg("%s", "Entering .......... \n");
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
- status = mos7840_write(port, &stop_char, 1);
- if (status <= 0) {
+ status = mos7840_write(tty, port, &stop_char, 1);
+ if (status <= 0)
return;
- }
}
-
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
mos7840_port->shadowMCR &= ~MCR_RTS;
- status = 0;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
-
- if (status < 0) {
+ if (status < 0)
return;
- }
}
return;
@@ -1625,12 +1582,13 @@ static void mos7840_throttle(struct usb_serial_port *port)
/*****************************************************************************
* mos7840_unthrottle
- * this function is called by the tty driver when it wants to resume the data
- * being read from the port (called after SerialThrottle is called)
+ * this function is called by the tty driver when it wants to resume
+ * the data being read from the port (called after mos7840_throttle is
+ * called)
*****************************************************************************/
-static void mos7840_unthrottle(struct usb_serial_port *port)
+static void mos7840_unthrottle(struct tty_struct *tty)
{
- struct tty_struct *tty;
+ struct usb_serial_port *port = tty->driver_data;
int status;
struct moschip_port *mos7840_port = mos7840_get_port_private(port);
@@ -1649,43 +1607,32 @@ static void mos7840_unthrottle(struct usb_serial_port *port)
dbg("%s", "Entering .......... \n");
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty available", __func__);
- return;
- }
-
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
unsigned char start_char = START_CHAR(tty);
- status = mos7840_write(port, &start_char, 1);
- if (status <= 0) {
+ status = mos7840_write(tty, port, &start_char, 1);
+ if (status <= 0)
return;
- }
}
/* if we are implementing RTS/CTS, toggle that line */
if (tty->termios->c_cflag & CRTSCTS) {
mos7840_port->shadowMCR |= MCR_RTS;
- status = 0;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
mos7840_port->shadowMCR);
- if (status < 0) {
+ if (status < 0)
return;
- }
}
-
- return;
}
-static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
unsigned int result;
__u16 msr;
__u16 mcr;
- int status = 0;
+ int status;
mos7840_port = mos7840_get_port_private(port);
dbg("%s - port %d", __func__, port->number);
@@ -1708,9 +1655,10 @@ static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
return result;
}
-static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port;
unsigned int mcr;
int status;
@@ -1755,7 +1703,7 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
* baud rate.
*****************************************************************************/
static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
- __u16 * clk_sel_val)
+ __u16 *clk_sel_val)
{
dbg("%s - %d", __func__, baudRate);
@@ -1807,9 +1755,8 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
/* Check for round off */
round1 = (__u16) (2304000L / baudrate);
round = (__u16) (round1 - (custom * 10));
- if (round > 4) {
+ if (round > 4)
custom++;
- }
*divisor = custom;
dbg(" Baud %d = %d\n", baudrate, custom);
@@ -1857,16 +1804,15 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
dbg("%s - port = %d, baud = %d", __func__,
mos7840_port->port->number, baudRate);
- //reset clk_uart_sel in spregOffset
+ /* reset clk_uart_sel in spregOffset */
if (baudRate > 115200) {
#ifdef HW_flow_control
- //NOTE: need to see the pther register to modify
- //setting h/w flow control bit to 1;
- status = 0;
+ /* NOTE: need to see the pther register to modify */
+ /* setting h/w flow control bit to 1 */
Data = 0x2b;
mos7840_port->shadowMCR = Data;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1875,12 +1821,11 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
} else {
#ifdef HW_flow_control
- //setting h/w flow control bit to 0;
- status = 0;
+ / *setting h/w flow control bit to 0 */
Data = 0xb;
mos7840_port->shadowMCR = Data;
- status =
- mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+ status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1889,25 +1834,20 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
}
- if (1) //baudRate <= 115200)
- {
+ if (1) { /* baudRate <= 115200) */
clk_sel_val = 0x0;
Data = 0x0;
- status = 0;
- status =
- mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+ status = mos7840_calc_baud_rate_divisor(baudRate, &divisor,
&clk_sel_val);
- status =
- mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
- &Data);
+ status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
+ &Data);
if (status < 0) {
dbg("reading spreg failed in set_serial_baud\n");
return -1;
}
Data = (Data & 0x8f) | clk_sel_val;
- status = 0;
- status =
- mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+ status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset,
+ Data);
if (status < 0) {
dbg("Writing spreg failed in set_serial_baud\n");
return -1;
@@ -1939,7 +1879,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
}
-
return status;
}
@@ -1949,10 +1888,9 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
* the specified new settings.
*****************************************************************************/
-static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
- struct ktermios *old_termios)
+static void mos7840_change_port_settings(struct tty_struct *tty,
+ struct moschip_port *mos7840_port, struct ktermios *old_termios)
{
- struct tty_struct *tty;
int baud;
unsigned cflag;
unsigned iflag;
@@ -1988,8 +1926,6 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
return;
}
- tty = mos7840_port->port->tty;
-
dbg("%s", "Entering .......... \n");
lData = LCR_BITS_8;
@@ -2033,9 +1969,8 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
dbg("%s - parity = none", __func__);
}
- if (cflag & CMSPAR) {
+ if (cflag & CMSPAR)
lParity = lParity | 0x20;
- }
/* Change the Stop bit */
if (cflag & CSTOPB) {
@@ -2077,16 +2012,13 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
/* set up the MCR register and send it to the mos7840 */
mos7840_port->shadowMCR = MCR_MASTER_IE;
- if (cflag & CBAUD) {
+ if (cflag & CBAUD)
mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
- }
- if (cflag & CRTSCTS) {
+ if (cflag & CRTSCTS)
mos7840_port->shadowMCR |= (MCR_XON_ANY);
-
- } else {
+ else
mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
- }
Data = mos7840_port->shadowMCR;
mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
@@ -2131,14 +2063,14 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
* the termios structure
*****************************************************************************/
-static void mos7840_set_termios(struct usb_serial_port *port,
+static void mos7840_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port,
struct ktermios *old_termios)
{
int status;
unsigned int cflag;
struct usb_serial *serial;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
dbg("mos7840_set_termios: START\n");
if (mos7840_port_paranoia_check(port, __func__)) {
dbg("%s", "Invalid port \n");
@@ -2157,8 +2089,6 @@ static void mos7840_set_termios(struct usb_serial_port *port,
if (mos7840_port == NULL)
return;
- tty = port->tty;
-
if (!mos7840_port->open) {
dbg("%s - port not opened", __func__);
return;
@@ -2176,7 +2106,7 @@ static void mos7840_set_termios(struct usb_serial_port *port,
/* change the port settings to the new ones specified */
- mos7840_change_port_settings(mos7840_port, old_termios);
+ mos7840_change_port_settings(tty, mos7840_port, old_termios);
if (!mos7840_port->read_urb) {
dbg("%s", "URB KILLED !!!!!\n");
@@ -2205,13 +2135,13 @@ static void mos7840_set_termios(struct usb_serial_port *port,
* allows an RS485 driver to be written in user space.
*****************************************************************************/
-static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+static int mos7840_get_lsr_info(struct tty_struct *tty,
unsigned int __user *value)
{
int count;
unsigned int result = 0;
- count = mos7840_chars_in_buffer(mos7840_port->port);
+ count = mos7840_chars_in_buffer(tty);
if (count == 0) {
dbg("%s -- Empty", __func__);
result = TIOCSER_TEMT;
@@ -2227,6 +2157,8 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
* function to set modem info
*****************************************************************************/
+/* FIXME: Should be using the model control hooks */
+
static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
unsigned int cmd, unsigned int __user *value)
{
@@ -2282,7 +2214,6 @@ static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
mos7840_port->shadowMCR = mcr;
Data = mos7840_port->shadowMCR;
- status = 0;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
if (status < 0) {
dbg("setting MODEM_CONTROL_REGISTER Failed\n");
@@ -2303,10 +2234,8 @@ static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
unsigned int result = 0;
__u16 msr;
unsigned int mcr = mos7840_port->shadowMCR;
- int status = 0;
- status =
- mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
- &msr);
+ mos7840_get_uart_reg(mos7840_port->port,
+ MODEM_STATUS_REGISTER, &msr);
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */
|((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */
|((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */
@@ -2359,12 +2288,12 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
* this function handles any ioctl calls to the driver
*****************************************************************************/
-static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
struct moschip_port *mos7840_port;
- struct tty_struct *tty;
struct async_icount cnow;
struct async_icount cprev;
@@ -2381,8 +2310,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
if (mos7840_port == NULL)
return -1;
- tty = mos7840_port->port->tty;
-
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
switch (cmd) {
@@ -2390,9 +2317,10 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
- return mos7840_get_lsr_info(mos7840_port, argp);
+ return mos7840_get_lsr_info(tty, argp);
return 0;
+ /* FIXME: use the modem hooks and remove this */
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
@@ -2418,7 +2346,7 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
cprev = mos7840_port->icount;
while (1) {
- //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+ /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
mos7840_port->delta_msr_cond = 0;
wait_event_interruptible(mos7840_port->delta_msr_wait,
(mos7840_port->
@@ -2463,13 +2391,9 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
if (copy_to_user(argp, &icount, sizeof(icount)))
return -EFAULT;
return 0;
-
- case TIOCEXBAUD:
- return 0;
default:
break;
}
-
return -ENOIOCTLCMD;
}
@@ -2527,8 +2451,9 @@ static int mos7840_startup(struct usb_serial *serial)
goto error;
}
- /* Initialize all port interrupt end point to port 0 int endpoint *
- * Our device has only one interrupt end point comman to all port */
+ /* Initialize all port interrupt end point to port 0 int
+ * endpoint. Our device has only one interrupt end point
+ * common to all port */
mos7840_port->port = serial->port[i];
mos7840_set_port_private(serial->port[i], mos7840_port);
@@ -2564,27 +2489,23 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_port->DcrRegOffset = 0x1c;
}
mos7840_dump_serial_port(mos7840_port);
-
mos7840_set_port_private(serial->port[i], mos7840_port);
- //enable rx_disable bit in control register
-
- status =
- mos7840_get_reg_sync(serial->port[i],
- mos7840_port->ControlRegOffset, &Data);
+ /* enable rx_disable bit in control register */
+ status = mos7840_get_reg_sync(serial->port[i],
+ mos7840_port->ControlRegOffset, &Data);
if (status < 0) {
dbg("Reading ControlReg failed status-0x%x\n", status);
break;
} else
dbg("ControlReg Reading success val is %x, status%d\n",
Data, status);
- Data |= 0x08; //setting driver done bit
- Data |= 0x04; //sp1_bit to have cts change reflect in modem status reg
+ Data |= 0x08; /* setting driver done bit */
+ Data |= 0x04; /* sp1_bit to have cts change reflect in
+ modem status reg */
- //Data |= 0x20; //rx_disable bit
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
+ /* Data |= 0x20; //rx_disable bit */
+ status = mos7840_set_reg_sync(serial->port[i],
mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
@@ -2593,13 +2514,11 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("ControlReg Writing success(rx_disable) status%d\n",
status);
- //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
+ /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+ and 0x24 in DCR3 */
Data = 0x01;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 0), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 0), Data);
if (status < 0) {
dbg("Writing DCR0 failed status-0x%x\n", status);
break;
@@ -2607,11 +2526,8 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR0 Writing success status%d\n", status);
Data = 0x05;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 1), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 1), Data);
if (status < 0) {
dbg("Writing DCR1 failed status-0x%x\n", status);
break;
@@ -2619,22 +2535,17 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("DCR1 Writing success status%d\n", status);
Data = 0x24;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
- (__u16) (mos7840_port->DcrRegOffset +
- 2), Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ (__u16) (mos7840_port->DcrRegOffset + 2), Data);
if (status < 0) {
dbg("Writing DCR2 failed status-0x%x\n", status);
break;
} else
dbg("DCR2 Writing success status%d\n", status);
- // write values in clkstart0x0 and clkmulti 0x20
+ /* write values in clkstart0x0 and clkmulti 0x20 */
Data = 0x0;
- status = 0;
- status =
- mos7840_set_reg_sync(serial->port[i],
+ status = mos7840_set_reg_sync(serial->port[i],
CLK_START_VALUE_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
@@ -2643,9 +2554,8 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
Data = 0x20;
- status =
- mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
- Data);
+ status = mos7840_set_reg_sync(serial->port[i],
+ CLK_MULTI_REGISTER, Data);
if (status < 0) {
dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
status);
@@ -2654,11 +2564,10 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("CLK_MULTI_REGISTER Writing success status%d\n",
status);
- //write value 0x0 to scratchpad register
+ /* write value 0x0 to scratchpad register */
Data = 0x00;
- status =
- mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
- Data);
+ status = mos7840_set_uart_reg(serial->port[i],
+ SCRATCH_PAD_REGISTER, Data);
if (status < 0) {
dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
status);
@@ -2667,21 +2576,17 @@ static int mos7840_startup(struct usb_serial *serial)
dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
status);
- //Zero Length flag register
+ /* Zero Length flag register */
if ((mos7840_port->port_num != 1)
&& (serial->num_ports == 2)) {
Data = 0xff;
- status = 0;
status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)
- mos7840_port->
- port_num)),
- Data);
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num)), Data);
dbg("ZLIP offset%x\n",
(__u16) (ZLP_REG1 +
- ((__u16) mos7840_port->port_num)));
+ ((__u16) mos7840_port->port_num)));
if (status < 0) {
dbg("Writing ZLP_REG%d failed status-0x%x\n",
i + 2, status);
@@ -2691,13 +2596,9 @@ static int mos7840_startup(struct usb_serial *serial)
i + 2, status);
} else {
Data = 0xff;
- status = 0;
status = mos7840_set_reg_sync(serial->port[i],
- (__u16) (ZLP_REG1 +
- ((__u16)
- mos7840_port->
- port_num) -
- 0x1), Data);
+ (__u16) (ZLP_REG1 +
+ ((__u16)mos7840_port->port_num) - 0x1), Data);
dbg("ZLIP offset%x\n",
(__u16) (ZLP_REG1 +
((__u16) mos7840_port->port_num) - 0x1));
@@ -2712,14 +2613,16 @@ static int mos7840_startup(struct usb_serial *serial)
}
mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
- mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
- if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
+ mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+ GFP_KERNEL);
+ if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+ !mos7840_port->dr) {
status = -ENOMEM;
goto error;
}
}
- //Zero Length flag enable
+ /* Zero Length flag enable */
Data = 0x0f;
status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
if (status < 0) {
@@ -2762,7 +2665,7 @@ static void mos7840_shutdown(struct usb_serial *serial)
return;
}
- /* check for the ports to be closed,close the ports and disconnect */
+ /* check for the ports to be closed,close the ports and disconnect */
/* free private structure allocated for serial port *
* stop reads and writes on all ports */
@@ -2843,20 +2746,12 @@ static int __init moschip7840_init(void)
/* Register with the usb */
retval = usb_register(&io_driver);
-
- if (retval)
- goto failed_usb_register;
-
if (retval == 0) {
dbg("%s\n", "Leaving...");
return 0;
}
-
- failed_usb_register:
usb_serial_deregister(&moschip7840_4port_device);
-
- failed_port_device_register:
-
+failed_port_device_register:
return retval;
}
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 43c8894353b..d6736531a0f 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -64,7 +64,7 @@ static void navman_read_int_callback(struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -79,7 +79,8 @@ exit:
__func__, result);
}
-static int navman_open(struct usb_serial_port *port, struct file *filp)
+static int navman_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int result = 0;
@@ -96,14 +97,15 @@ static int navman_open(struct usb_serial_port *port, struct file *filp)
return result;
}
-static void navman_close(struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->interrupt_in_urb);
}
-static int navman_write(struct usb_serial_port *port,
+static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 7b7422f4947..ae8e227f3db 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -5,26 +5,28 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* Please report both successes and troubles to the author at omninet@kroah.com
- *
+ *
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (08/28/2000) gkh
* Added locks for SMP safeness.
- * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
* than once.
* Fixed potential race in omninet_write_bulk_callback
*
@@ -43,7 +45,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -58,25 +60,29 @@ static int debug;
#define ZYXEL_VENDOR_ID 0x0586
#define ZYXEL_OMNINET_ID 0x1000
-#define BT_IGNITIONPRO_ID 0x2000 /* This one seems to be a re-branded ZyXEL device */
+/* This one seems to be a re-branded ZyXEL device */
+#define BT_IGNITIONPRO_ID 0x2000
/* function prototypes */
-static int omninet_open (struct usb_serial_port *port, struct file *filp);
-static void omninet_close (struct usb_serial_port *port, struct file *filp);
-static void omninet_read_bulk_callback (struct urb *urb);
-static void omninet_write_bulk_callback (struct urb *urb);
-static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int omninet_write_room (struct usb_serial_port *port);
-static void omninet_shutdown (struct usb_serial *serial);
-static int omninet_attach (struct usb_serial *serial);
-
-static struct usb_device_id id_table [] = {
+static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_write_bulk_callback(struct urb *urb);
+static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int omninet_write_room(struct tty_struct *tty);
+static void omninet_shutdown(struct usb_serial *serial);
+static int omninet_attach(struct usb_serial *serial);
+
+static struct usb_device_id id_table[] = {
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver omninet_driver = {
.name = "omninet",
@@ -130,34 +136,34 @@ static struct usb_serial_driver zyxel_omninet_device = {
*
*/
-struct omninet_header
-{
+struct omninet_header {
__u8 oh_seq;
__u8 oh_len;
__u8 oh_xxx;
__u8 oh_pad;
};
-struct omninet_data
-{
- __u8 od_outseq; // Sequence number for bulk_out URBs
+struct omninet_data {
+ __u8 od_outseq; /* Sequence number for bulk_out URBs */
};
-static int omninet_attach (struct usb_serial *serial)
+static int omninet_attach(struct usb_serial *serial)
{
struct omninet_data *od;
struct usb_serial_port *port = serial->port[0];
- od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
- if( !od ) {
- err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
+ od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
+ if (!od) {
+ err("%s- kmalloc(%Zd) failed.",
+ __func__, sizeof(struct omninet_data));
return -ENOMEM;
}
usb_set_serial_port_data(port, od);
return 0;
}
-static int omninet_open (struct usb_serial_port *port, struct file *filp)
+static int omninet_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport;
@@ -166,22 +172,24 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __func__, port->number);
wport = serial->port[1];
- wport->tty = port->tty;
+ wport->port.tty = tty; /* FIXME */
/* Start reading from the device */
- usb_fill_bulk_urb(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ omninet_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
- if (result) {
- err("%s - failed submitting read urb, error %d", __func__, result);
- }
-
+ if (result)
+ err("%s - failed submitting read urb, error %d",
+ __func__, result);
return result;
}
-static void omninet_close (struct usb_serial_port *port, struct file * filp)
+static void omninet_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __func__, port->number);
usb_kill_urb(port->read_urb);
@@ -192,14 +200,14 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
#define OMNINET_HEADERLEN sizeof(struct omninet_header)
#define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN)
-static void omninet_read_bulk_callback (struct urb *urb)
+static void omninet_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
struct omninet_header *header = (struct omninet_header *) &data[0];
int status = urb->status;
- int i;
int result;
+ int i;
dbg("%s - port %d", __func__, port->number);
@@ -209,42 +217,46 @@ static void omninet_read_bulk_callback (struct urb *urb)
return;
}
- if ((debug) && (header->oh_xxx != 0x30)) {
+ if (debug && header->oh_xxx != 0x30) {
if (urb->actual_length) {
- printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
- for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
- printk ("%.2x ", data[i]);
- }
- printk ("\n");
+ printk(KERN_DEBUG __FILE__
+ ": omninet_read %d: ", header->oh_len);
+ for (i = 0; i < (header->oh_len +
+ OMNINET_HEADERLEN); i++)
+ printk("%.2x ", data[i]);
+ printk("\n");
}
}
if (urb->actual_length && header->oh_len) {
- for (i = 0; i < header->oh_len; i++) {
- tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0);
- }
- tty_flip_buffer_push(port->tty);
+ tty_insert_flip_string(port->port.tty,
+ data + OMNINET_DATAOFFSET, header->oh_len);
+ tty_flip_buffer_push(port->port.tty);
}
/* Continue trying to always read */
- usb_fill_bulk_urb(urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
- omninet_read_bulk_callback, port);
+ usb_fill_bulk_urb(urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ omninet_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
return;
}
-static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
- struct usb_serial *serial = port->serial;
- struct usb_serial_port *wport = serial->port[1];
+ struct usb_serial *serial = port->serial;
+ struct usb_serial_port *wport = serial->port[1];
- struct omninet_data *od = usb_get_serial_port_data(port);
- struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
+ struct omninet_data *od = usb_get_serial_port_data(port);
+ struct omninet_header *header = (struct omninet_header *)
+ wport->write_urb->transfer_buffer;
int result;
@@ -252,7 +264,7 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
if (count == 0) {
dbg("%s - write request of 0 bytes", __func__);
- return (0);
+ return 0;
}
spin_lock_bh(&wport->lock);
@@ -266,9 +278,11 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
- memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
+ memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+ buf, count);
- usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ wport->write_urb->transfer_buffer);
header->oh_seq = od->od_outseq++;
header->oh_len = count;
@@ -282,7 +296,8 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
wport->write_urb_busy = 0;
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
} else
result = count;
@@ -290,8 +305,9 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf
}
-static int omninet_write_room (struct usb_serial_port *port)
+static int omninet_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport = serial->port[1];
@@ -303,12 +319,13 @@ static int omninet_write_room (struct usb_serial_port *port)
dbg("%s - returns %d", __func__, room);
- return (room);
+ return room;
}
-static void omninet_write_bulk_callback (struct urb *urb)
+static void omninet_write_bulk_callback(struct urb *urb)
{
-/* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */
+/* struct omninet_header *header = (struct omninet_header *)
+ urb->transfer_buffer; */
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -325,18 +342,18 @@ static void omninet_write_bulk_callback (struct urb *urb)
}
-static void omninet_shutdown (struct usb_serial *serial)
+static void omninet_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *wport = serial->port[1];
struct usb_serial_port *port = serial->port[0];
- dbg ("%s", __func__);
+ dbg("%s", __func__);
usb_kill_urb(wport->write_urb);
kfree(usb_get_serial_port_data(port));
}
-static int __init omninet_init (void)
+static int __init omninet_init(void)
{
int retval;
retval = usb_serial_register(&zyxel_omninet_device);
@@ -354,18 +371,18 @@ failed_usb_serial_register:
}
-static void __exit omninet_exit (void)
+static void __exit omninet_exit(void)
{
- usb_deregister (&omninet_driver);
- usb_serial_deregister (&zyxel_omninet_device);
+ usb_deregister(&omninet_driver);
+ usb_serial_deregister(&zyxel_omninet_device);
}
module_init(omninet_init);
module_exit(omninet_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index a73420dd052..e4eca95f2b0 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -43,29 +43,25 @@
#include <linux/usb/serial.h>
/* Function prototypes */
-static int option_open(struct usb_serial_port *port, struct file *filp);
-static void option_close(struct usb_serial_port *port, struct file *filp);
+static int option_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
static int option_startup(struct usb_serial *serial);
static void option_shutdown(struct usb_serial *serial);
-static void option_rx_throttle(struct usb_serial_port *port);
-static void option_rx_unthrottle(struct usb_serial_port *port);
-static int option_write_room(struct usb_serial_port *port);
+static int option_write_room(struct tty_struct *tty);
static void option_instat_callback(struct urb *urb);
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-
-static int option_chars_in_buffer(struct usb_serial_port *port);
-static int option_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg);
-static void option_set_termios(struct usb_serial_port *port,
- struct ktermios *old);
-static void option_break_ctl(struct usb_serial_port *port, int break_state);
-static int option_tiocmget(struct usb_serial_port *port, struct file *file);
-static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int option_chars_in_buffer(struct tty_struct *tty);
+static void option_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int option_tiocmget(struct tty_struct *tty, struct file *file);
+static int option_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
-static int option_send_setup(struct usb_serial_port *port);
+static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
/* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0
@@ -173,6 +169,7 @@ static int option_send_setup(struct usb_serial_port *port);
#define DELL_VENDOR_ID 0x413C
#define KYOCERA_VENDOR_ID 0x0c88
+#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
#define ANYDATA_VENDOR_ID 0x16d5
@@ -305,6 +302,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
+ { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
@@ -340,11 +338,7 @@ static struct usb_serial_driver option_1port_device = {
.write = option_write,
.write_room = option_write_room,
.chars_in_buffer = option_chars_in_buffer,
- .throttle = option_rx_throttle,
- .unthrottle = option_rx_unthrottle,
- .ioctl = option_ioctl,
.set_termios = option_set_termios,
- .break_ctl = option_break_ctl,
.tiocmget = option_tiocmget,
.tiocmset = option_tiocmset,
.attach = option_startup,
@@ -401,47 +395,32 @@ static int __init option_init(void)
return 0;
failed_driver_register:
- usb_serial_deregister (&option_1port_device);
+ usb_serial_deregister(&option_1port_device);
failed_1port_device_register:
return retval;
}
static void __exit option_exit(void)
{
- usb_deregister (&option_driver);
- usb_serial_deregister (&option_1port_device);
+ usb_deregister(&option_driver);
+ usb_serial_deregister(&option_1port_device);
}
module_init(option_init);
module_exit(option_exit);
-static void option_rx_throttle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void option_rx_unthrottle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void option_break_ctl(struct usb_serial_port *port, int break_state)
-{
- /* Unfortunately, I don't know how to send a break */
- dbg("%s", __func__);
-}
-
-static void option_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void option_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s", __func__);
/* Doesn't support option setting */
- tty_termios_copy_hw(port->tty->termios, old_termios);
- option_send_setup(port);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ option_send_setup(tty, port);
}
-static int option_tiocmget(struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int value;
struct option_port_private *portdata;
@@ -457,9 +436,10 @@ static int option_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int option_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
portdata = usb_get_serial_port_data(port);
@@ -474,17 +454,11 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return option_send_setup(port);
-}
-
-static int option_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
+ return option_send_setup(tty, port);
}
/* Write */
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct option_port_private *portdata;
@@ -499,7 +473,7 @@ static int option_write(struct usb_serial_port *port,
i = 0;
left = count;
- for (i=0; left > 0 && i < N_OUT_URB; i++) {
+ for (i = 0; left > 0 && i < N_OUT_URB; i++) {
todo = left;
if (todo > OUT_BUFLEN)
todo = OUT_BUFLEN;
@@ -520,7 +494,7 @@ static int option_write(struct usb_serial_port *port,
usb_pipeendpoint(this_urb->pipe), i);
/* send the data */
- memcpy (this_urb->transfer_buffer, buf, todo);
+ memcpy(this_urb->transfer_buffer, buf, todo);
this_urb->transfer_buffer_length = todo;
this_urb->dev = port->serial->dev;
@@ -560,7 +534,7 @@ static void option_indat_callback(struct urb *urb)
dbg("%s: nonzero status: %d on endpoint %02x.",
__func__, status, endpoint);
} else {
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -570,7 +544,7 @@ static void option_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && status != -ESHUTDOWN) {
+ if (port->port.count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -611,7 +585,7 @@ static void option_instat_callback(struct urb *urb)
struct usb_serial *serial = port->serial;
dbg("%s", __func__);
- dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
+ dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
if (status == 0) {
struct usb_ctrlrequest *req_pkt =
@@ -636,12 +610,12 @@ static void option_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty) &&
+ if (port->port.tty && !C_CLOCAL(port->port.tty) &&
old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
} else {
dbg("%s: type %x req %x", __func__,
- req_pkt->bRequestType,req_pkt->bRequest);
+ req_pkt->bRequestType, req_pkt->bRequest);
}
} else
dbg("%s: error %d", __func__, status);
@@ -656,8 +630,9 @@ static void option_instat_callback(struct urb *urb)
}
}
-static int option_write_room(struct usb_serial_port *port)
+static int option_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
int i;
int data_len = 0;
@@ -666,7 +641,7 @@ static int option_write_room(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- for (i=0; i < N_OUT_URB; i++) {
+ for (i = 0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
if (this_urb && !test_bit(i, &portdata->out_busy))
data_len += OUT_BUFLEN;
@@ -676,8 +651,9 @@ static int option_write_room(struct usb_serial_port *port)
return data_len;
}
-static int option_chars_in_buffer(struct usb_serial_port *port)
+static int option_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct option_port_private *portdata;
int i;
int data_len = 0;
@@ -685,7 +661,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- for (i=0; i < N_OUT_URB; i++) {
+ for (i = 0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
/* FIXME: This locking is insufficient as this_urb may
go unused during the test */
@@ -696,7 +672,8 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
return data_len;
}
-static int option_open(struct usb_serial_port *port, struct file *filp)
+static int option_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct option_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -714,7 +691,7 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < N_IN_URB; i++) {
urb = portdata->in_urbs[i];
- if (! urb)
+ if (!urb)
continue;
if (urb->dev != serial->dev) {
dbg("%s: dev %p != %p", __func__,
@@ -739,21 +716,23 @@ static int option_open(struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle on out endpoints */
for (i = 0; i < N_OUT_URB; i++) {
urb = portdata->out_urbs[i];
- if (! urb)
+ if (!urb)
continue;
urb->dev = serial->dev;
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), 0); */
}
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
- option_send_setup(port);
+ option_send_setup(tty, port);
- return (0);
+ return 0;
}
-static void option_close(struct usb_serial_port *port, struct file *filp)
+static void option_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -768,7 +747,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
- option_send_setup(port);
+ option_send_setup(tty, port);
mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
@@ -777,7 +756,7 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
for (i = 0; i < N_OUT_URB; i++)
usb_kill_urb(portdata->out_urbs[i]);
}
- port->tty = NULL;
+ port->port.tty = NULL; /* FIXME */
}
/* Helper functions used by option_setup_urbs */
@@ -807,7 +786,7 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
/* Setup urbs */
static void option_setup_urbs(struct usb_serial *serial)
{
- int i,j;
+ int i, j;
struct usb_serial_port *port;
struct option_port_private *portdata;
@@ -817,18 +796,22 @@ static void option_setup_urbs(struct usb_serial *serial)
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
- /* Do indat endpoints first */
+ /* Do indat endpoints first */
for (j = 0; j < N_IN_URB; ++j) {
- portdata->in_urbs[j] = option_setup_urb (serial,
- port->bulk_in_endpointAddress, USB_DIR_IN, port,
- portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+ portdata->in_urbs[j] = option_setup_urb(serial,
+ port->bulk_in_endpointAddress,
+ USB_DIR_IN, port,
+ portdata->in_buffer[j],
+ IN_BUFLEN, option_indat_callback);
}
/* outdat endpoints */
for (j = 0; j < N_OUT_URB; ++j) {
- portdata->out_urbs[j] = option_setup_urb (serial,
- port->bulk_out_endpointAddress, USB_DIR_OUT, port,
- portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+ portdata->out_urbs[j] = option_setup_urb(serial,
+ port->bulk_out_endpointAddress,
+ USB_DIR_OUT, port,
+ portdata->out_buffer[j],
+ OUT_BUFLEN, option_outdat_callback);
}
}
}
@@ -839,7 +822,8 @@ static void option_setup_urbs(struct usb_serial *serial)
* This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
* CDC.
*/
-static int option_send_setup(struct usb_serial_port *port)
+static int option_send_setup(struct tty_struct *tty,
+ struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct option_port_private *portdata;
@@ -848,7 +832,7 @@ static int option_send_setup(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- if (port->tty) {
+ if (tty) {
int val = 0;
if (portdata->dtr_state)
val |= 0x01;
@@ -856,10 +840,9 @@ static int option_send_setup(struct usb_serial_port *port)
val |= 0x02;
return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}
-
return 0;
}
@@ -879,7 +862,7 @@ static int option_startup(struct usb_serial *serial)
if (!portdata) {
dbg("%s: kmalloc for option_port_private (%d) failed!.",
__func__, i);
- return (1);
+ return 1;
}
for (j = 0; j < N_IN_URB; j++) {
@@ -898,17 +881,15 @@ static int option_startup(struct usb_serial *serial)
usb_set_serial_port_data(port, portdata);
- if (! port->interrupt_in_urb)
+ if (!port->interrupt_in_urb)
continue;
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
dbg("%s: submit irq_in urb failed %d",
__func__, err);
}
-
option_setup_urbs(serial);
-
- return (0);
+ return 0;
bail_out_error2:
for (j = 0; j < N_OUT_URB; j++)
@@ -947,7 +928,8 @@ static void option_shutdown(struct usb_serial *serial)
for (j = 0; j < N_IN_URB; j++) {
if (portdata->in_urbs[j]) {
usb_free_urb(portdata->in_urbs[j]);
- free_page((unsigned long)portdata->in_buffer[j]);
+ free_page((unsigned long)
+ portdata->in_buffer[j]);
portdata->in_urbs[j] = NULL;
}
}
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a9625c180dc..81db5715ee2 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -25,7 +25,8 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* TODO:
* - implement correct flushing for ioctls and oti6858_close()
@@ -49,7 +50,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "oti6858.h"
#define OTI6858_DESCRIPTION \
@@ -135,27 +136,28 @@ struct oti6858_control_pkt {
#define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt)
#define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
- ( ((a)->divisor == (priv)->pending_setup.divisor) \
+ (((a)->divisor == (priv)->pending_setup.divisor) \
&& ((a)->control == (priv)->pending_setup.control) \
- && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+ && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt))
/* function prototypes */
-static int oti6858_open(struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct usb_serial_port *port, struct file *filp);
-static void oti6858_set_termios(struct usb_serial_port *port,
- struct ktermios *old);
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
static void oti6858_read_int_callback(struct urb *urb);
static void oti6858_read_bulk_callback(struct urb *urb);
static void oti6858_write_bulk_callback(struct urb *urb);
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
-static int oti6858_write_room(struct usb_serial_port *port);
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
-static int oti6858_chars_in_buffer(struct usb_serial_port *port);
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_write_room(struct tty_struct *tty);
+static int oti6858_chars_in_buffer(struct tty_struct *tty);
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static int oti6858_startup(struct usb_serial *serial);
static void oti6858_shutdown(struct usb_serial *serial);
@@ -184,7 +186,6 @@ static struct usb_serial_driver oti6858_device = {
.close = oti6858_close,
.write = oti6858_write,
.ioctl = oti6858_ioctl,
- .break_ctl = oti6858_break_ctl,
.set_termios = oti6858_set_termios,
.tiocmget = oti6858_tiocmget,
.tiocmset = oti6858_tiocmset,
@@ -220,7 +221,7 @@ struct oti6858_private {
struct delayed_work delayed_setup_work;
wait_queue_head_t intr_wait;
- struct usb_serial_port *port; /* USB port with which associated */
+ struct usb_serial_port *port; /* USB port with which associated */
};
#undef dbg
@@ -229,7 +230,8 @@ struct oti6858_private {
static void setup_line(struct work_struct *work)
{
- struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+ struct oti6858_private *priv = container_of(work,
+ struct oti6858_private, delayed_setup_work.work);
struct usb_serial_port *port = priv->port;
struct oti6858_control_pkt *new_setup;
unsigned long flags;
@@ -237,10 +239,12 @@ static void setup_line(struct work_struct *work)
dbg("%s(port = %d)", __func__, port->number);
- if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+ if (new_setup == NULL) {
dev_err(&port->dev, "%s(): out of memory!\n", __func__);
/* we will try again */
- schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_setup_work,
+ msecs_to_jiffies(2));
return;
}
@@ -256,7 +260,8 @@ static void setup_line(struct work_struct *work)
dev_err(&port->dev, "%s(): error reading status\n", __func__);
kfree(new_setup);
/* we will try again */
- schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_setup_work,
+ msecs_to_jiffies(2));
return;
}
@@ -297,7 +302,8 @@ static void setup_line(struct work_struct *work)
void send_data(struct work_struct *work)
{
- struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+ struct oti6858_private *priv = container_of(work,
+ struct oti6858_private, delayed_write_work.work);
struct usb_serial_port *port = priv->port;
int count = 0, result;
unsigned long flags;
@@ -308,7 +314,8 @@ void send_data(struct work_struct *work)
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use) {
spin_unlock_irqrestore(&priv->lock, flags);
- schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+ schedule_delayed_work(&priv->delayed_write_work,
+ msecs_to_jiffies(2));
return;
}
priv->flags.write_urb_in_use = 1;
@@ -359,8 +366,8 @@ void send_data(struct work_struct *work)
static int oti6858_startup(struct usb_serial *serial)
{
- struct usb_serial_port *port = serial->port[0];
- struct oti6858_private *priv;
+ struct usb_serial_port *port = serial->port[0];
+ struct oti6858_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
@@ -375,8 +382,8 @@ static int oti6858_startup(struct usb_serial *serial)
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->intr_wait);
-// INIT_WORK(&priv->setup_work, setup_line, serial->port[i]);
-// INIT_WORK(&priv->write_work, send_data, serial->port[i]);
+/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
+/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
priv->port = port;
INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -395,7 +402,7 @@ static int oti6858_startup(struct usb_serial *serial)
return -ENOMEM;
}
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -413,8 +420,9 @@ static int oti6858_write(struct usb_serial_port *port,
return count;
}
-static int oti6858_write_room(struct usb_serial_port *port)
+static int oti6858_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -428,8 +436,9 @@ static int oti6858_write_room(struct usb_serial_port *port)
return room;
}
-static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+static int oti6858_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -443,8 +452,8 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void oti6858_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void oti6858_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -455,22 +464,22 @@ static void oti6858_set_termios(struct usb_serial_port *port,
dbg("%s(port = %d)", __func__, port->number);
- if (!port->tty || !port->tty->termios) {
+ if (!tty) {
dbg("%s(): no tty structures", __func__);
return;
}
spin_lock_irqsave(&priv->lock, flags);
if (!priv->flags.termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 38400;
+ tty->termios->c_ospeed = 38400;
priv->flags.termios_initialized = 1;
- port->tty->termios->c_ispeed = 38400;
- port->tty->termios->c_ospeed = 38400;
}
spin_unlock_irqrestore(&priv->lock, flags);
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
spin_lock_irqsave(&priv->lock, flags);
divisor = priv->pending_setup.divisor;
@@ -480,19 +489,19 @@ static void oti6858_set_termios(struct usb_serial_port *port,
frame_fmt &= ~FMT_DATA_BITS_MASK;
switch (cflag & CSIZE) {
- case CS5:
- frame_fmt |= FMT_DATA_BITS_5;
- break;
- case CS6:
- frame_fmt |= FMT_DATA_BITS_6;
- break;
- case CS7:
- frame_fmt |= FMT_DATA_BITS_7;
- break;
- default:
- case CS8:
- frame_fmt |= FMT_DATA_BITS_8;
- break;
+ case CS5:
+ frame_fmt |= FMT_DATA_BITS_5;
+ break;
+ case CS6:
+ frame_fmt |= FMT_DATA_BITS_6;
+ break;
+ case CS7:
+ frame_fmt |= FMT_DATA_BITS_7;
+ break;
+ default:
+ case CS8:
+ frame_fmt |= FMT_DATA_BITS_8;
+ break;
}
/* manufacturer claims that this device can work with baud rates
@@ -500,7 +509,7 @@ static void oti6858_set_termios(struct usb_serial_port *port,
* guarantee that any other baud rate will work (especially
* the higher ones)
*/
- br = tty_get_baud_rate(port->tty);
+ br = tty_get_baud_rate(tty);
if (br == 0) {
divisor = 0;
} else {
@@ -511,23 +520,21 @@ static void oti6858_set_termios(struct usb_serial_port *port,
new_divisor = (96000000 + 8 * br) / (16 * br);
real_br = 96000000 / (16 * new_divisor);
divisor = cpu_to_le16(new_divisor);
- tty_encode_baud_rate(port->tty, real_br, real_br);
+ tty_encode_baud_rate(tty, real_br, real_br);
}
frame_fmt &= ~FMT_STOP_BITS_MASK;
- if ((cflag & CSTOPB) != 0) {
+ if ((cflag & CSTOPB) != 0)
frame_fmt |= FMT_STOP_BITS_2;
- } else {
+ else
frame_fmt |= FMT_STOP_BITS_1;
- }
frame_fmt &= ~FMT_PARITY_MASK;
if ((cflag & PARENB) != 0) {
- if ((cflag & PARODD) != 0) {
+ if ((cflag & PARODD) != 0)
frame_fmt |= FMT_PARITY_ODD;
- } else {
+ else
frame_fmt |= FMT_PARITY_EVEN;
- }
} else {
frame_fmt |= FMT_PARITY_NONE;
}
@@ -564,7 +571,8 @@ static void oti6858_set_termios(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
}
-static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+static int oti6858_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
struct ktermios tmp_termios;
@@ -578,10 +586,11 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
- if (port->open_count != 1)
+ if (port->port.count != 1)
return 0;
- if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+ if (buf == NULL) {
dev_err(&port->dev, "%s(): out of memory!\n", __func__);
return -ENOMEM;
}
@@ -617,18 +626,19 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result);
- oti6858_close(port, NULL);
+ oti6858_close(tty, port, NULL);
return -EPROTO;
}
/* setup termios */
- if (port->tty)
- oti6858_set_termios(port, &tmp_termios);
+ if (tty)
+ oti6858_set_termios(tty, port, &tmp_termios);
return 0;
}
-static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -641,7 +651,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
dbg("%s(): entering wait loop", __func__);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -654,7 +664,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
dbg("%s(): after wait loop", __func__);
/* clear out any remaining data in the buffer */
@@ -669,7 +679,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
/* data is in the buffer to compute a delay */
/* that is not unnecessarily long) */
/* FIXME
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ*2560)/bps,HZ/10);
else
@@ -690,7 +700,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->interrupt_in_urb);
/*
- if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+ if (tty && (tty->termios->c_cflag) & HUPCL) {
// drop DTR and RTS
spin_lock_irqsave(&priv->lock, flags);
priv->pending_setup.control &= ~CONTROL_MASK;
@@ -699,9 +709,10 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
*/
}
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -724,16 +735,16 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
if ((clear & TIOCM_DTR) != 0)
control &= ~CONTROL_DTR_HIGH;
- if (control != priv->pending_setup.control) {
+ if (control != priv->pending_setup.control)
priv->pending_setup.control = control;
- }
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct oti6858_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned pin_state;
@@ -779,7 +790,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+ wait_event_interruptible(priv->intr_wait,
+ priv->status.pin_state != prev);
if (signal_pending(current))
return -ERESTARTSYS;
@@ -789,12 +801,11 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
changed = prev ^ status;
/* FIXME: check if this is correct (active high/low) */
- if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
- ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
- ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
- return 0;
- }
+ if (((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+ ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+ ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
+ ((arg & TIOCM_CTS) && (changed & PIN_CTS)))
+ return 0;
prev = status;
}
@@ -802,56 +813,25 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- void __user *user_arg = (void __user *) arg;
- unsigned int x;
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
__func__, port->number, cmd, arg);
switch (cmd) {
- case TIOCMBIS:
- if (copy_from_user(&x, user_arg, sizeof(x)))
- return -EFAULT;
- return oti6858_tiocmset(port, NULL, x, 0);
-
- case TIOCMBIC:
- if (copy_from_user(&x, user_arg, sizeof(x)))
- return -EFAULT;
- return oti6858_tiocmset(port, NULL, 0, x);
-
- case TIOCMIWAIT:
- dbg("%s(): TIOCMIWAIT", __func__);
- return wait_modem_info(port, arg);
-
- default:
- dbg("%s(): 0x%04x not supported", __func__, cmd);
- break;
+ case TIOCMIWAIT:
+ dbg("%s(): TIOCMIWAIT", __func__);
+ return wait_modem_info(port, arg);
+ default:
+ dbg("%s(): 0x%04x not supported", __func__, cmd);
+ break;
}
-
return -ENOIOCTLCMD;
}
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
-{
- int state;
-
- dbg("%s(port = %d)", __func__, port->number);
-
- state = (break_state == 0) ? 0 : 1;
- dbg("%s(): turning break %s", __func__, state ? "on" : "off");
-
- /* FIXME */
-/*
- result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
- BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
- 0, NULL, 0, 100);
- if (result != 0)
- dbg("%s(): error sending break", __func__);
- */
-}
static void oti6858_shutdown(struct usb_serial *serial)
{
@@ -964,7 +944,7 @@ static void oti6858_read_int_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use == 0
&& oti6858_buf_data_avail(priv->buf) != 0) {
- schedule_delayed_work(&priv->delayed_write_work,0);
+ schedule_delayed_work(&priv->delayed_write_work, 0);
resubmit = 0;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -973,7 +953,7 @@ static void oti6858_read_int_callback(struct urb *urb)
if (resubmit) {
int result;
-// dbg("%s(): submitting interrupt urb", __func__);
+/* dbg("%s(): submitting interrupt urb", __func__); */
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result != 0) {
@@ -1002,14 +982,16 @@ static void oti6858_read_bulk_callback(struct urb *urb)
spin_unlock_irqrestore(&priv->lock, flags);
if (status != 0) {
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s(): port is closed, exiting", __func__);
return;
}
/*
if (status == -EPROTO) {
- // PL2303 mysteriously fails with -EPROTO reschedule the read
- dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
+ * PL2303 mysteriously fails with -EPROTO reschedule
+ the read *
+ dbg("%s - caught -EPROTO, resubmitting the urb",
+ __func__);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
@@ -1020,14 +1002,14 @@ static void oti6858_read_bulk_callback(struct urb *urb)
return;
}
- tty = port->tty;
+ tty = port->port.tty;
if (tty != NULL && urb->actual_length > 0) {
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
- // schedule the interrupt urb if we are still open */
- if (port->open_count != 0) {
+ /* schedule the interrupt urb if we are still open */
+ if (port->port.count != 0) {
port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result != 0) {
@@ -1078,7 +1060,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
priv->flags.write_urb_in_use = 0;
- // schedule the interrupt urb if we are still open */
+ /* schedule the interrupt urb if we are still open */
port->interrupt_in_urb->dev = port->serial->dev;
dbg("%s(): submitting interrupt urb", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
@@ -1153,7 +1135,7 @@ static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/*
@@ -1166,7 +1148,7 @@ static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/*
@@ -1253,13 +1235,12 @@ static int __init oti6858_init(void)
{
int retval;
- if ((retval = usb_serial_register(&oti6858_device)) == 0) {
- if ((retval = usb_register(&oti6858_driver)) != 0)
+ retval = usb_serial_register(&oti6858_device);
+ if (retval == 0) {
+ retval = usb_register(&oti6858_driver);
+ if (retval)
usb_serial_deregister(&oti6858_device);
- else
- return 0;
}
-
return retval;
}
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2a0dd1b50dc..2c9c446ad62 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -10,7 +10,8 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -25,7 +26,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "pl2303.h"
@@ -116,7 +117,7 @@ static struct usb_driver pl2303_driver = {
#define CONTROL_RTS 0x02
#define BREAK_REQUEST_TYPE 0x21
-#define BREAK_REQUEST 0x23
+#define BREAK_REQUEST 0x23
#define BREAK_ON 0xffff
#define BREAK_OFF 0x0000
@@ -222,7 +223,7 @@ static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/*
@@ -236,7 +237,7 @@ static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/*
@@ -395,7 +396,7 @@ static int pl2303_startup(struct usb_serial *serial)
cleanup:
kfree(buf);
- for (--i; i>=0; --i) {
+ for (--i; i >= 0; --i) {
priv = usb_get_serial_port_data(serial->port[i]);
pl2303_buf_free(priv->buf);
kfree(priv);
@@ -407,7 +408,7 @@ cleanup:
static int set_control_lines(struct usb_device *dev, u8 value)
{
int retval;
-
+
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
value, 0, NULL, 0, 100);
@@ -452,14 +453,14 @@ static void pl2303_send(struct usb_serial_port *port)
dev_err(&port->dev, "%s - failed submitting write urb,"
" error %d\n", __func__, result);
priv->write_urb_in_use = 0;
- // TODO: reschedule pl2303_send
+ /* TODO: reschedule pl2303_send */
}
usb_serial_port_softint(port);
}
-static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
- int count)
+static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -478,8 +479,9 @@ static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
return count;
}
-static int pl2303_write_room(struct usb_serial_port *port)
+static int pl2303_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -494,8 +496,9 @@ static int pl2303_write_room(struct usb_serial_port *port)
return room;
}
-static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+static int pl2303_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -510,8 +513,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
return chars;
}
-static void pl2303_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void pl2303_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -526,11 +529,10 @@ static void pl2303_set_termios(struct usb_serial_port *port,
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
- HUPCL | CLOCAL;
- port->tty->termios->c_ispeed = 9600;
- port->tty->termios->c_ospeed = 9600;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 9600;
+ tty->termios->c_ospeed = 9600;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -539,16 +541,16 @@ static void pl2303_set_termios(struct usb_serial_port *port,
serial settings even to the same values as before. Thus
we actually need to filter in this specific case */
- if (!tty_termios_hw_change(port->tty->termios, old_termios))
+ if (!tty_termios_hw_change(tty->termios, old_termios))
return;
- cflag = port->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __func__);
/* Report back no change occurred */
- *port->tty->termios = *old_termios;
+ *tty->termios = *old_termios;
return;
}
@@ -560,16 +562,24 @@ static void pl2303_set_termios(struct usb_serial_port *port,
if (cflag & CSIZE) {
switch (cflag & CSIZE) {
- case CS5: buf[6] = 5; break;
- case CS6: buf[6] = 6; break;
- case CS7: buf[6] = 7; break;
- default:
- case CS8: buf[6] = 8; break;
+ case CS5:
+ buf[6] = 5;
+ break;
+ case CS6:
+ buf[6] = 6;
+ break;
+ case CS7:
+ buf[6] = 7;
+ break;
+ default:
+ case CS8:
+ buf[6] = 8;
+ break;
}
dbg("%s - data bits = %d", __func__, buf[6]);
}
- baud = tty_get_baud_rate(port->tty);;
+ baud = tty_get_baud_rate(tty);
dbg("%s - baud = %d", __func__, baud);
if (baud) {
buf[0] = baud & 0xff;
@@ -646,12 +656,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
/* FIXME: Need to read back resulting baud rate */
if (baud)
- tty_encode_baud_rate(port->tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
kfree(buf);
}
-static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -666,7 +677,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = PL2303_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (pl2303_buf_data_avail(priv->buf) == 0 ||
@@ -678,7 +689,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
pl2303_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -690,9 +701,9 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
/* for lower rates we should really know how much */
/* data is in the buffer to compute a delay */
/* that is not unnecessarily long) */
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
- timeout = max((HZ*2560)/bps,HZ/10);
+ timeout = max((HZ*2560)/bps, HZ/10);
else
timeout = 2*HZ;
schedule_timeout_interruptible(timeout);
@@ -703,8 +714,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
@@ -715,7 +726,8 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
}
}
-static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+static int pl2303_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -734,11 +746,10 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
}
/* Setup termios */
- if (port->tty) {
- pl2303_set_termios(port, &tmp_termios);
- }
+ if (tty)
+ pl2303_set_termios(tty, port, &tmp_termios);
- //FIXME: need to assert RTS and DTR if CRTSCTS off
+ /* FIXME: need to assert RTS and DTR if CRTSCTS off */
dbg("%s - submitting read urb", __func__);
port->read_urb->dev = serial->dev;
@@ -746,7 +757,7 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting read urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
@@ -756,15 +767,16 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (result) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, result);
- pl2303_close(port, NULL);
+ pl2303_close(tty, port, NULL);
return -EPROTO;
}
return 0;
}
-static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -787,8 +799,9 @@ static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
return set_control_lines(port->serial->dev, control);
}
-static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
@@ -839,12 +852,12 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
- changed=prevstatus^status;
+ changed = prevstatus ^ status;
if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
((arg & TIOCM_CD) && (changed & UART_DCD)) ||
- ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
+ ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
return 0;
}
prevstatus = status;
@@ -853,26 +866,26 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
return 0;
}
-static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCMIWAIT:
- dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
- return wait_modem_info(port, arg);
-
- default:
- dbg("%s not supported = 0x%04x", __func__, cmd);
- break;
+ case TIOCMIWAIT:
+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ return wait_modem_info(port, arg);
+ default:
+ dbg("%s not supported = 0x%04x", __func__, cmd);
+ break;
}
-
return -ENOIOCTLCMD;
}
-static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
u16 state;
int result;
@@ -883,7 +896,8 @@ static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
state = BREAK_OFF;
else
state = BREAK_ON;
- dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
+ dbg("%s - turning break %s", __func__,
+ state == BREAK_OFF ? "off" : "on");
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
@@ -937,7 +951,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
if (actual_length < length)
return;
- /* Save off the uart status for others to look at */
+ /* Save off the uart status for others to look at */
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = data[status_idx];
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1001,7 +1015,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
if (status) {
dbg("%s - urb status = %d", __func__, status);
- if (!port->open_count) {
+ if (!port->port.count) {
dbg("%s - port is closed, exiting.", __func__);
return;
}
@@ -1036,7 +1050,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
- if (line_status & UART_BREAK_ERROR )
+ if (line_status & UART_BREAK_ERROR)
tty_flag = TTY_BREAK;
else if (line_status & UART_PARITY_ERROR)
tty_flag = TTY_PARITY;
@@ -1044,7 +1058,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __func__, tty_flag);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -1056,7 +1070,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 94bddf06ea4..def52d07a4e 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -13,24 +13,25 @@
* Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
*/
-/*
- * The encapsultaion is designed to overcome difficulties with some USB hardware.
+/*
+ * The encapsultaion is designed to overcome difficulties with some USB
+ * hardware.
*
* While the USB protocol has a CRC over the data while in transit, i.e. while
- * being carried over the bus, there is no end to end protection. If the hardware
- * has any problems getting the data into or out of the USB transmit and receive
- * FIFO's then data can be lost.
+ * being carried over the bus, there is no end to end protection. If the
+ * hardware has any problems getting the data into or out of the USB transmit
+ * and receive FIFO's then data can be lost.
*
- * This protocol adds a two byte trailer to each USB packet to specify the number
- * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify
- * that the entire USB packet was received without error.
+ * This protocol adds a two byte trailer to each USB packet to specify the
+ * number of bytes of valid data and a 10 bit CRC that will allow the receiver
+ * to verify that the entire USB packet was received without error.
*
- * Because in this case the sender and receiver are the class and function drivers
- * there is now end to end protection.
+ * Because in this case the sender and receiver are the class and function
+ * drivers there is now end to end protection.
*
- * There is an additional option that can be used to force all transmitted packets
- * to be padded to the maximum packet size. This provides a work around for some
- * devices which have problems with small USB packets.
+ * There is an additional option that can be used to force all transmitted
+ * packets to be padded to the maximum packet size. This provides a work
+ * around for some devices which have problems with small USB packets.
*
* Assuming a packetsize of N:
*
@@ -44,11 +45,12 @@
* | Data Length | 10 bit CRC |
* + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
*
- * The 10 bit CRC is computed across the sent data, followed by the trailer with
- * the length set and the CRC set to zero. The CRC is then OR'd into the trailer.
+ * The 10 bit CRC is computed across the sent data, followed by the trailer
+ * with the length set and the CRC set to zero. The CRC is then OR'd into
+ * the trailer.
*
- * When received a 10 bit CRC is computed over the entire frame including the trailer
- * and should be equal to zero.
+ * When received a 10 bit CRC is computed over the entire frame including
+ * the trailer and should be equal to zero.
*
* Two module parameters are used to control the encapsulation, if both are
* turned of the module works as a simple serial device with NO
@@ -69,7 +71,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -86,12 +88,12 @@ static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
#define DRIVER_DESC "USB Safe Encapsulated Serial"
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static __u16 vendor; // no default
-static __u16 product; // no default
+static __u16 vendor; /* no default */
+static __u16 product; /* no default */
module_param(vendor, ushort, 0);
MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
module_param(product, ushort, 0);
@@ -122,30 +124,31 @@ MODULE_PARM_DESC(padded, "Pad to full wMaxPacketSize On/Off");
#define LINEO_SAFESERIAL_CRC_PADDED 0x02
-#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \
- USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
- .idVendor = (vend), \
- .idProduct = (prod),\
- .bDeviceClass = (dc),\
- .bInterfaceClass = (ic), \
- .bInterfaceSubClass = (isc),
+#define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_DEV_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
+ .idVendor = (vend), \
+ .idProduct = (prod),\
+ .bDeviceClass = (dc),\
+ .bInterfaceClass = (ic), \
+ .bInterfaceSubClass = (isc),
static struct usb_device_id id_table[] = {
- {MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Itsy
- {MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Calypso
- {MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Iris
- {MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Collie
- {MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, // Sharp tmp
- // extra null entry for module
- // vendor/produc parameters
- {MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
- {} // terminating entry
+ {MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Itsy */
+ {MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Calypso */
+ {MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Iris */
+ {MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */
+ {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */
+ /* extra null entry for module vendor/produc parameters */
+ {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
+ {} /* terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver safe_driver = {
.name = "safe_serial",
@@ -156,29 +159,45 @@ static struct usb_driver safe_driver = {
};
static const __u16 crc10_table[256] = {
- 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
- 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
- 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
- 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
- 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
- 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
- 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
- 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
- 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
- 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
- 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
- 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
- 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
- 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
- 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
- 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
+ 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
+ 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
+ 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
+ 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
+ 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
+ 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
+ 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
+ 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
+ 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
+ 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
+ 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
+ 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
+ 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
+ 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
+ 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
+ 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
+ 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
+ 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
+ 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
+ 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
+ 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
+ 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
+ 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
+ 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
+ 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
+ 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
+ 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
+ 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
+ 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
+ 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
+ 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
+ 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
};
-#define CRC10_INITFCS 0x000 // Initial FCS value
-#define CRC10_GOODFCS 0x000 // Good final FCS value
-#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
+#define CRC10_INITFCS 0x000 /* Initial FCS value */
+#define CRC10_GOODFCS 0x000 /* Good final FCS value */
+#define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
-/**
+/**
* fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
* @sp: pointer to buffer
* @len: number of bytes
@@ -187,13 +206,13 @@ static const __u16 crc10_table[256] = {
* Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
* new 10 bit FCS.
*/
-static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+static __u16 __inline__ fcs_compute10(unsigned char *sp, int len, __u16 fcs)
{
- for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++));
+ for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
return fcs;
}
-static void safe_read_bulk_callback (struct urb *urb)
+static void safe_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
@@ -201,7 +220,7 @@ static void safe_read_bulk_callback (struct urb *urb)
int result;
int status = urb->status;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
if (status) {
dbg("%s - nonzero read bulk status received: %d",
@@ -209,76 +228,82 @@ static void safe_read_bulk_callback (struct urb *urb)
return;
}
- dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length);
+ dbg("safe_read_bulk_callback length: %d",
+ port->read_urb->actual_length);
#ifdef ECHO_RCV
{
int i;
unsigned char *cp = port->read_urb->transfer_buffer;
for (i = 0; i < port->read_urb->actual_length; i++) {
- if ((i % 32) == 0) {
- printk ("\nru[%02x] ", i);
- }
- printk ("%02x ", *cp++);
+ if ((i % 32) == 0)
+ printk("\nru[%02x] ", i);
+ printk("%02x ", *cp++);
}
- printk ("\n");
+ printk("\n");
}
#endif
if (safe) {
__u16 fcs;
- if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+ fcs = fcs_compute10(data, length, CRC10_INITFCS);
+ if (!fcs) {
int actual_length = data[length - 2] >> 2;
if (actual_length <= (length - 2)) {
- info ("%s - actual: %d", __func__, actual_length);
- tty_insert_flip_string(port->tty, data, actual_length);
- tty_flip_buffer_push (port->tty);
+ info("%s - actual: %d", __func__,
+ actual_length);
+ tty_insert_flip_string(port->port.tty,
+ data, actual_length);
+ tty_flip_buffer_push(port->port.tty);
} else {
- err ("%s - inconsistent lengths %d:%d", __func__,
- actual_length, length);
+ err("%s - inconsistent lengths %d:%d",
+ __func__, actual_length, length);
}
} else {
- err ("%s - bad CRC %x", __func__, fcs);
+ err("%s - bad CRC %x", __func__, fcs);
}
} else {
- tty_insert_flip_string(port->tty, data, length);
- tty_flip_buffer_push (port->tty);
+ tty_insert_flip_string(port->port.tty, data, length);
+ tty_flip_buffer_push(port->port.tty);
}
/* Continue trying to always read */
- usb_fill_bulk_urb (urb, port->serial->dev,
- usb_rcvbulkpipe (port->serial->dev, port->bulk_in_endpointAddress),
- urb->transfer_buffer, urb->transfer_buffer_length,
- safe_read_bulk_callback, port);
-
- if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
- err ("%s - failed resubmitting read urb, error %d", __func__, result);
+ usb_fill_bulk_urb(urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ safe_read_bulk_callback, port);
+
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
/* FIXME: Need a mechanism to retry later if this happens */
- }
}
-static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
unsigned char *data;
int result;
int i;
int packet_length;
- dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb,
- count);
+ dbg("safe_write port: %p %d urb: %p count: %d",
+ port, port->number, port->write_urb, count);
if (!port->write_urb) {
- dbg ("%s - write urb NULL", __func__);
+ dbg("%s - write urb NULL", __func__);
return 0;
}
- dbg ("safe_write write_urb: %d transfer_buffer_length",
+ dbg("safe_write write_urb: %d transfer_buffer_length",
port->write_urb->transfer_buffer_length);
if (!port->write_urb->transfer_buffer_length) {
- dbg ("%s - write urb transfer_buffer_length zero", __func__);
+ dbg("%s - write urb transfer_buffer_length zero", __func__);
return 0;
}
if (count == 0) {
- dbg ("%s - write request of 0 bytes", __func__);
+ dbg("%s - write request of 0 bytes", __func__);
return 0;
}
spin_lock_bh(&port->lock);
@@ -290,85 +315,85 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i
port->write_urb_busy = 1;
spin_unlock_bh(&port->lock);
- packet_length = port->bulk_out_size; // get max packetsize
+ packet_length = port->bulk_out_size; /* get max packetsize */
- i = packet_length - (safe ? 2 : 0); // get bytes to send
+ i = packet_length - (safe ? 2 : 0); /* get bytes to send */
count = (count > i) ? i : count;
- // get the data into the transfer buffer
+ /* get the data into the transfer buffer */
data = port->write_urb->transfer_buffer;
- memset (data, '0', packet_length);
+ memset(data, '0', packet_length);
- memcpy (data, buf, count);
+ memcpy(data, buf, count);
if (safe) {
__u16 fcs;
- // pad if necessary
- if (!padded) {
+ /* pad if necessary */
+ if (!padded)
packet_length = count + 2;
- }
- // set count
+ /* set count */
data[packet_length - 2] = count << 2;
data[packet_length - 1] = 0;
- // compute fcs and insert into trailer
- fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS);
+ /* compute fcs and insert into trailer */
+ fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
data[packet_length - 2] |= fcs >> 8;
data[packet_length - 1] |= fcs & 0xff;
- // set length to send
+ /* set length to send */
port->write_urb->transfer_buffer_length = packet_length;
} else {
port->write_urb->transfer_buffer_length = count;
}
- usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
#ifdef ECHO_TX
{
int i;
unsigned char *cp = port->write_urb->transfer_buffer;
for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
- if ((i % 32) == 0) {
- printk ("\nsu[%02x] ", i);
- }
- printk ("%02x ", *cp++);
+ if ((i % 32) == 0)
+ printk("\nsu[%02x] ", i);
+ printk("%02x ", *cp++);
}
- printk ("\n");
+ printk("\n");
}
#endif
port->write_urb->dev = port->serial->dev;
- if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+ result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ if (result) {
port->write_urb_busy = 0;
- err ("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
return 0;
}
- dbg ("%s urb: %p submitted", __func__, port->write_urb);
+ dbg("%s urb: %p submitted", __func__, port->write_urb);
- return (count);
+ return count;
}
-static int safe_write_room (struct usb_serial_port *port)
+static int safe_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
int room = 0; /* Default: no room */
unsigned long flags;
- dbg ("%s", __func__);
+ dbg("%s", __func__);
spin_lock_irqsave(&port->lock, flags);
if (port->write_urb_busy)
room = port->bulk_out_size - (safe ? 2 : 0);
spin_unlock_irqrestore(&port->lock, flags);
- if (room) {
- dbg ("safe_write_room returns %d", room);
- }
-
+ if (room)
+ dbg("safe_write_room returns %d", room);
return room;
}
-static int safe_startup (struct usb_serial *serial)
+static int safe_startup(struct usb_serial *serial)
{
switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
case LINEO_SAFESERIAL_CRC:
@@ -396,17 +421,18 @@ static struct usb_serial_driver safe_device = {
.attach = safe_startup,
};
-static int __init safe_init (void)
+static int __init safe_init(void)
{
int i, retval;
- info (DRIVER_VERSION " " DRIVER_AUTHOR);
- info (DRIVER_DESC);
- info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded);
+ info(DRIVER_VERSION " " DRIVER_AUTHOR);
+ info(DRIVER_DESC);
+ info("vendor: %x product: %x safe: %d padded: %d\n",
+ vendor, product, safe, padded);
- // if we have vendor / product parameters patch them into id list
+ /* if we have vendor / product parameters patch them into id list */
if (vendor || product) {
- info ("vendor: %x product: %x\n", vendor, product);
+ info("vendor: %x product: %x\n", vendor, product);
for (i = 0; i < ARRAY_SIZE(id_table); i++) {
if (!id_table[i].idVendor && !id_table[i].idProduct) {
@@ -431,11 +457,11 @@ failed_usb_serial_register:
return retval;
}
-static void __exit safe_exit (void)
+static void __exit safe_exit(void)
{
- usb_deregister (&safe_driver);
- usb_serial_deregister (&safe_device);
+ usb_deregister(&safe_driver);
+ usb_serial_deregister(&safe_device);
}
-module_init (safe_init);
-module_exit (safe_exit);
+module_init(safe_init);
+module_exit(safe_exit);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 29074c1ba22..2f6f1523ec5 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -250,7 +250,8 @@ struct sierra_port_private {
int ri_state;
};
-static int sierra_send_setup(struct usb_serial_port *port)
+static int sierra_send_setup(struct tty_struct *tty,
+ struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
@@ -260,7 +261,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
portdata = usb_get_serial_port_data(port);
- if (port->tty) {
+ if (tty) {
int val = 0;
if (portdata->dtr_state)
val |= 0x01;
@@ -284,32 +285,17 @@ static int sierra_send_setup(struct usb_serial_port *port)
return 0;
}
-static void sierra_rx_throttle(struct usb_serial_port *port)
+static void sierra_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s", __func__);
+ tty_termios_copy_hw(tty->termios, old_termios);
+ sierra_send_setup(tty, port);
}
-static void sierra_rx_unthrottle(struct usb_serial_port *port)
-{
- dbg("%s", __func__);
-}
-
-static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
-{
- /* Unfortunately, I don't know how to send a break */
- dbg("%s", __func__);
-}
-
-static void sierra_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
-{
- dbg("%s", __func__);
- tty_termios_copy_hw(port->tty->termios, old_termios);
- sierra_send_setup(port);
-}
-
-static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
+static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
unsigned int value;
struct sierra_port_private *portdata;
@@ -325,9 +311,10 @@ static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
return value;
}
-static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
+static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct sierra_port_private *portdata;
portdata = usb_get_serial_port_data(port);
@@ -341,13 +328,7 @@ static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
portdata->rts_state = 0;
if (clear & TIOCM_DTR)
portdata->dtr_state = 0;
- return sierra_send_setup(port);
-}
-
-static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
+ return sierra_send_setup(tty, port);
}
static void sierra_outdat_callback(struct urb *urb)
@@ -374,8 +355,8 @@ static void sierra_outdat_callback(struct urb *urb)
}
/* Write */
-static int sierra_write(struct usb_serial_port *port,
- const unsigned char *buf, int count)
+static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -463,7 +444,7 @@ static void sierra_indat_callback(struct urb *urb)
dbg("%s: nonzero status: %d on endpoint %02x.",
__func__, status, endpoint);
} else {
- tty = port->tty;
+ tty = port->port.tty;
if (urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
tty_insert_flip_string(tty, data, urb->actual_length);
@@ -473,7 +454,7 @@ static void sierra_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && status != -ESHUTDOWN) {
+ if (port->port.count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
dev_err(&port->dev, "resubmit read urb failed."
@@ -517,9 +498,9 @@ static void sierra_instat_callback(struct urb *urb)
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
- if (port->tty && !C_CLOCAL(port->tty) &&
+ if (port->port.tty && !C_CLOCAL(port->port.tty) &&
old_dcd_state && !portdata->dcd_state)
- tty_hangup(port->tty);
+ tty_hangup(port->port.tty);
} else {
dbg("%s: type %x req %x", __func__,
req_pkt->bRequestType, req_pkt->bRequest);
@@ -537,8 +518,9 @@ static void sierra_instat_callback(struct urb *urb)
}
}
-static int sierra_write_room(struct usb_serial_port *port)
+static int sierra_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
unsigned long flags;
@@ -557,22 +539,8 @@ static int sierra_write_room(struct usb_serial_port *port)
return 2048;
}
-static int sierra_chars_in_buffer(struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device as we can't see the backend here, so just
- * tell the tty layer that everything is flushed.
- *
- * FIXME: should walk the outstanding urbs info
- */
- return 0;
-}
-
-static int sierra_open(struct usb_serial_port *port, struct file *filp)
+static int sierra_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct sierra_port_private *portdata;
struct usb_serial *serial = port->serial;
@@ -612,9 +580,10 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
}
}
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
- sierra_send_setup(port);
+ sierra_send_setup(tty, port);
/* start up the interrupt endpoint if we have one */
if (port->interrupt_in_urb) {
@@ -626,7 +595,8 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
return 0;
}
-static void sierra_close(struct usb_serial_port *port, struct file *filp)
+static void sierra_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int i;
struct usb_serial *serial = port->serial;
@@ -641,7 +611,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
if (!serial->disconnected)
- sierra_send_setup(port);
+ sierra_send_setup(tty, port);
mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
@@ -651,7 +621,7 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
usb_kill_urb(port->interrupt_in_urb);
- port->tty = NULL;
+ port->port.tty = NULL; /* FIXME */
}
static int sierra_startup(struct usb_serial *serial)
@@ -754,12 +724,7 @@ static struct usb_serial_driver sierra_device = {
.close = sierra_close,
.write = sierra_write,
.write_room = sierra_write_room,
- .chars_in_buffer = sierra_chars_in_buffer,
- .throttle = sierra_rx_throttle,
- .unthrottle = sierra_rx_unthrottle,
- .ioctl = sierra_ioctl,
.set_termios = sierra_set_termios,
- .break_ctl = sierra_break_ctl,
.tiocmget = sierra_tiocmget,
.tiocmset = sierra_tiocmset,
.attach = sierra_startup,
@@ -792,7 +757,7 @@ failed_device_register:
static void __exit sierra_exit(void)
{
- usb_deregister (&sierra_driver);
+ usb_deregister(&sierra_driver);
usb_serial_deregister(&sierra_device);
}
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 55b2570b8b8..283cf6b36b2 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -208,7 +208,7 @@ static inline unsigned int ringbuf_avail_data(struct ringbuf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+ return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
}
/* get the number of space in the pipo */
@@ -216,7 +216,7 @@ static inline unsigned int ringbuf_avail_space(struct ringbuf *pb)
{
if (pb == NULL)
return 0;
- return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+ return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
}
/* put count data into pipo */
@@ -448,7 +448,8 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
/* close the serial port. We should wait for data sending to device 1st and
* then kill all urb. */
-static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -464,7 +465,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
timeout = SPCP8x5_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
- add_wait_queue(&port->tty->write_wait, &wait);
+ add_wait_queue(&tty->write_wait, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (ringbuf_avail_data(priv->buf) == 0 ||
@@ -475,7 +476,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
spin_lock_irqsave(&priv->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->tty->write_wait, &wait);
+ remove_wait_queue(&tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
clear_ringbuf(priv->buf);
@@ -486,7 +487,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
* flow control for data rates of 1200 bps or more, for lower rates we
* should really know how much data is in the buffer to compute a delay
* that is not unnecessarily long) */
- bps = tty_get_baud_rate(port->tty);
+ bps = tty_get_baud_rate(tty);
if (bps > 1200)
timeout = max((HZ*2560) / bps, HZ/10);
else
@@ -495,8 +496,8 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
schedule_timeout(timeout);
/* clear control lines */
- if (port->tty) {
- c_cflag = port->tty->termios->c_cflag;
+ if (tty) {
+ c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
@@ -518,14 +519,14 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
}
/* set the serial param for transfer. we should check if we really need to
- * transfer. then if be set flow contorl we should do this too. */
-static void spcp8x5_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+ * transfer. if we set flow control we should do this too. */
+static void spcp8x5_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
- unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned int cflag = tty->termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned short uartdata;
unsigned char buf[2] = {0, 0};
@@ -533,21 +534,19 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
int i;
u8 control;
- if ((!port->tty) || (!port->tty->termios))
- return;
-
/* for the 1st time call this function */
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
- *(port->tty->termios) = tty_std_termios;
- port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
- HUPCL | CLOCAL;
+ *(tty->termios) = tty_std_termios;
+ tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ tty->termios->c_ispeed = 115200;
+ tty->termios->c_ospeed = 115200;
priv->termios_initialized = 1;
}
spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
- if (!tty_termios_hw_change(port->tty->termios, old_termios))
+ if (!tty_termios_hw_change(tty->termios, old_termios))
return;
/* set DTR/RTS active */
@@ -567,7 +566,7 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
}
/* Set Baud Rate */
- baud = tty_get_baud_rate(port->tty);;
+ baud = tty_get_baud_rate(tty);;
switch (baud) {
case 300: buf[0] = 0x00; break;
case 600: buf[0] = 0x01; break;
@@ -643,7 +642,8 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
/* open the serial port. do some usb system call. set termios and get the line
* status of the device. then submit the read urb */
-static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
+static int spcp8x5_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
@@ -665,7 +665,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
return ret;
spin_lock_irqsave(&priv->lock, flags);
- if (port->tty->termios->c_cflag & CBAUD)
+ if (tty && (tty->termios->c_cflag & CBAUD))
priv->line_control = MCR_DTR | MCR_RTS;
else
priv->line_control = 0;
@@ -674,8 +674,8 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
/* Setup termios */
- if (port->tty)
- spcp8x5_set_termios(port, &tmp_termios);
+ if (tty)
+ spcp8x5_set_termios(tty, port, &tmp_termios);
spcp8x5_get_msr(serial->dev, &status, priv->type);
@@ -690,7 +690,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
port->read_urb->dev = serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (ret) {
- spcp8x5_close(port, NULL);
+ spcp8x5_close(tty, port, NULL);
return -EPROTO;
}
return 0;
@@ -717,7 +717,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
/* check the urb status */
if (urb->status) {
- if (!port->open_count)
+ if (!port->port.count)
return;
if (urb->status == -EPROTO) {
/* spcp8x5 mysteriously fails with -EPROTO */
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
tty_flag = TTY_FRAME;
dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
@@ -767,7 +767,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
}
/* Schedule the next read _if_ we are still open */
- if (port->open_count) {
+ if (port->port.count) {
urb->dev = port->serial->dev;
result = usb_submit_urb(urb , GFP_ATOMIC);
if (result)
@@ -866,7 +866,7 @@ static void spcp8x5_write_bulk_callback(struct urb *urb)
}
/* write data to ring buffer. and then start the write transfer */
-static int spcp8x5_write(struct usb_serial_port *port,
+static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -925,9 +925,10 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
return 0;
}
-static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
@@ -943,9 +944,10 @@ static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
-static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
@@ -965,8 +967,9 @@ static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
}
-static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
+static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
@@ -989,8 +992,9 @@ static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
}
/* get the avail space room in ring buffer */
-static int spcp8x5_write_room(struct usb_serial_port *port)
+static int spcp8x5_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -1003,8 +1007,9 @@ static int spcp8x5_write_room(struct usb_serial_port *port)
}
/* get the number of avail data in write ring buffer */
-static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
+static int spcp8x5_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct spcp8x5_private *priv = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a26a629dfc4..e39c779e416 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -16,7 +16,7 @@
* For questions or problems with this driver, contact Texas Instruments
* technical support, or Al Borchers <alborchers@steinerpoint.com>, or
* Peter Berger <pberger@brimson.com>.
- *
+ *
* This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052
* or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device
* configuration.
@@ -70,6 +70,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/firmware.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
@@ -81,7 +82,7 @@
#include <linux/serial.h>
#include <linux/circ_buf.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/firmware.h>
@@ -149,21 +150,24 @@ struct ti_device {
static int ti_startup(struct usb_serial *serial);
static void ti_shutdown(struct usb_serial *serial);
-static int ti_open(struct usb_serial_port *port, struct file *file);
-static void ti_close(struct usb_serial_port *port, struct file *file);
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
- int count);
-static int ti_write_room(struct usb_serial_port *port);
-static int ti_chars_in_buffer(struct usb_serial_port *port);
-static void ti_throttle(struct usb_serial_port *port);
-static void ti_unthrottle(struct usb_serial_port *port);
-static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void ti_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios);
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
- unsigned int set, unsigned int clear);
-static void ti_break(struct usb_serial_port *port, int break_state);
+static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file);
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file);
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count);
+static int ti_write_room(struct tty_struct *tty);
+static int ti_chars_in_buffer(struct tty_struct *tty);
+static void ti_throttle(struct tty_struct *tty);
+static void ti_unthrottle(struct tty_struct *tty);
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void ti_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios);
+static int ti_tiocmget(struct tty_struct *tty, struct file *file);
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void ti_break(struct tty_struct *tty, int break_state);
static void ti_interrupt_callback(struct urb *urb);
static void ti_bulk_in_callback(struct urb *urb);
static void ti_bulk_out_callback(struct urb *urb);
@@ -192,8 +196,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
__u8 mask, __u8 byte);
-static int ti_download_firmware(struct ti_device *tdev, char *fw_name);
-
+static int ti_download_firmware(struct ti_device *tdev, int type);
/* circular buffer */
static struct circ_buf *ti_buf_alloc(void);
@@ -325,19 +328,25 @@ module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off");
+MODULE_PARM_DESC(low_latency,
+ "TTY low_latency flag, 0=off, 1=on, default is off");
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000");
+MODULE_PARM_DESC(closing_wait,
+ "Maximum wait for data to drain in close, in .01 secs, default is 4000");
module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_3410,
+ "Vendor ids for 3410 based devices, 1-5 short integers");
module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
-MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_3410,
+ "Product ids for 3410 based devices, 1-5 short integers");
module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_5052,
+ "Vendor ids for 5052 based devices, 1-5 short integers");
module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
-MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_5052,
+ "Product ids for 5052 based devices, 1-5 short integers");
MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
@@ -346,18 +355,18 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
static int __init ti_init(void)
{
- int i,j;
+ int i, j;
int ret;
/* insert extra vendor and product ids */
j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
+ for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) {
ti_id_table_3410[j].idVendor = vendor_3410[i];
ti_id_table_3410[j].idProduct = product_3410[i];
ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
- for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
+ for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) {
ti_id_table_5052[j].idVendor = vendor_5052[i];
ti_id_table_5052[j].idProduct = product_5052[i];
ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
@@ -426,15 +435,15 @@ static int ti_startup(struct usb_serial *serial)
/* determine device type */
if (usb_match_id(serial->interface, ti_id_table_3410))
tdev->td_is_3410 = 1;
- dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
+ dbg("%s - device type is %s", __func__,
+ tdev->td_is_3410 ? "3410" : "5052");
/* if we have only 1 configuration, download firmware */
if (dev->descriptor.bNumConfigurations == 1) {
-
if (tdev->td_is_3410)
- status = ti_download_firmware(tdev, "ti_3410.fw");
+ status = ti_download_firmware(tdev, 3410);
else
- status = ti_download_firmware(tdev, "ti_5052.fw");
+ status = ti_download_firmware(tdev, 5052);
if (status)
goto free_tdev;
@@ -446,7 +455,7 @@ static int ti_startup(struct usb_serial *serial)
status = -ENODEV;
goto free_tdev;
- }
+ }
/* the second configuration must be set (in sysfs by hotplug script) */
if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {
@@ -463,7 +472,8 @@ static int ti_startup(struct usb_serial *serial)
goto free_tports;
}
spin_lock_init(&tport->tp_lock);
- tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
+ tport->tp_uart_base_addr = (i == 0 ?
+ TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
tport->tp_closing_wait = closing_wait;
init_waitqueue_head(&tport->tp_msr_wait);
@@ -480,11 +490,11 @@ static int ti_startup(struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], tport);
tport->tp_uart_mode = 0; /* default is RS232 */
}
-
+
return 0;
free_tports:
- for (--i; i>=0; --i) {
+ for (--i; i >= 0; --i) {
tport = usb_get_serial_port_data(serial->port[i]);
ti_buf_free(tport->tp_write_buf);
kfree(tport);
@@ -505,7 +515,7 @@ static void ti_shutdown(struct usb_serial *serial)
dbg("%s", __func__);
- for (i=0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i) {
tport = usb_get_serial_port_data(serial->port[i]);
if (tport) {
ti_buf_free(tport->tp_write_buf);
@@ -519,7 +529,8 @@ static void ti_shutdown(struct usb_serial *serial)
}
-static int ti_open(struct usb_serial_port *port, struct file *file)
+static int ti_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *file)
{
struct ti_port *tport = usb_get_serial_port_data(port);
struct ti_device *tdev;
@@ -527,8 +538,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
struct urb *urb;
int port_number;
int status;
- __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
- TI_PIPE_TIMEOUT_ENABLE |
+ __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
+ TI_PIPE_TIMEOUT_ENABLE |
(TI_TRANSFER_TIMEOUT << 2));
dbg("%s - port %d", __func__, port->number);
@@ -543,9 +554,9 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
- if (port->tty)
- port->tty->low_latency =
- (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ if (tty)
+ tty->low_latency =
+ (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
port_number = port->number - port->serial->minor;
@@ -559,7 +570,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
dbg("%s - start interrupt in urb", __func__);
urb = tdev->td_serial->port[0]->interrupt_in_urb;
if (!urb) {
- dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
+ dev_err(&port->dev, "%s - no interrupt urb\n",
+ __func__);
status = -EINVAL;
goto release_lock;
}
@@ -568,18 +580,22 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - submit interrupt urb failed, %d\n",
+ __func__, status);
goto release_lock;
}
}
- ti_set_termios(port, port->tty->termios);
+ if (tty)
+ ti_set_termios(tty, port, tty->termios);
dbg("%s - sending TI_OPEN_PORT", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send open command, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -587,7 +603,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send start command, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -595,13 +612,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot clear input buffers, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot clear output buffers, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -610,13 +629,15 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
usb_clear_halt(dev, port->write_urb->pipe);
usb_clear_halt(dev, port->read_urb->pipe);
- ti_set_termios(port, port->tty->termios);
+ if (tty)
+ ti_set_termios(tty, port, tty->termios);
dbg("%s - sending TI_OPEN_PORT (2)", __func__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send open command (2), %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -624,7 +645,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status) {
- dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot send start command (2), %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -642,7 +664,8 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
urb->dev = dev;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
- dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - submit read urb failed, %d\n",
+ __func__, status);
goto unlink_int_urb;
}
@@ -661,7 +684,8 @@ release_lock:
}
-static void ti_close(struct usb_serial_port *port, struct file *file)
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *file)
{
struct ti_device *tdev;
struct ti_port *tport;
@@ -670,7 +694,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
int do_unlock;
dbg("%s - port %d", __func__, port->number);
-
+
tdev = usb_get_serial_data(port->serial);
tport = usb_get_serial_port_data(port);
if (tdev == NULL || tport == NULL)
@@ -690,7 +714,9 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
if (status)
- dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
+ dev_err(&port->dev,
+ "%s - cannot send close port command, %d\n"
+ , __func__, status);
/* if mutex_lock is interrupted, continue anyway */
do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
@@ -707,8 +733,8 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
}
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
- int count)
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *data, int count)
{
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned long flags;
@@ -733,8 +759,9 @@ static int ti_write(struct usb_serial_port *port, const unsigned char *data,
}
-static int ti_write_room(struct usb_serial_port *port)
+static int ti_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int room = 0;
unsigned long flags;
@@ -743,7 +770,7 @@ static int ti_write_room(struct usb_serial_port *port)
if (tport == NULL)
return -ENODEV;
-
+
spin_lock_irqsave(&tport->tp_lock, flags);
room = ti_buf_space_avail(tport->tp_write_buf);
spin_unlock_irqrestore(&tport->tp_lock, flags);
@@ -753,8 +780,9 @@ static int ti_write_room(struct usb_serial_port *port)
}
-static int ti_chars_in_buffer(struct usb_serial_port *port)
+static int ti_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int chars = 0;
unsigned long flags;
@@ -773,32 +801,26 @@ static int ti_chars_in_buffer(struct usb_serial_port *port)
}
-static void ti_throttle(struct usb_serial_port *port)
+static void ti_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
if (tport == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty", __func__);
- return;
- }
-
if (I_IXOFF(tty) || C_CRTSCTS(tty))
ti_stop_read(tport, tty);
}
-static void ti_unthrottle(struct usb_serial_port *port)
+static void ti_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty;
int status;
dbg("%s - port %d", __func__, port->number);
@@ -806,23 +828,19 @@ static void ti_unthrottle(struct usb_serial_port *port)
if (tport == NULL)
return;
- tty = port->tty;
- if (!tty) {
- dbg("%s - no tty", __func__);
- return;
- }
-
if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
status = ti_restart_read(tport, tty);
if (status)
- dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
+ dev_err(&port->dev, "%s - cannot restart read, %d\n",
+ __func__, status);
}
}
-static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
@@ -833,55 +851,52 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
return -ENODEV;
switch (cmd) {
- case TIOCGSERIAL:
- dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
- return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
- break;
-
- case TIOCSSERIAL:
- dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
- return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
- break;
-
- case TIOCMIWAIT:
- dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
- cprev = tport->tp_icount;
- while (1) {
- interruptible_sleep_on(&tport->tp_msr_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- cnow = tport->tp_icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
- return 0;
- }
- cprev = cnow;
- }
- break;
-
- case TIOCGICOUNT:
- dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
- if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
- return -EFAULT;
- return 0;
+ case TIOCGSERIAL:
+ dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+ return ti_get_serial_info(tport,
+ (struct serial_struct __user *)arg);
+ case TIOCSSERIAL:
+ dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+ return ti_set_serial_info(tport,
+ (struct serial_struct __user *)arg);
+ case TIOCMIWAIT:
+ dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+ cprev = tport->tp_icount;
+ while (1) {
+ interruptible_sleep_on(&tport->tp_msr_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = tport->tp_icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
+ return 0;
+ cprev = cnow;
+ }
+ break;
+ case TIOCGICOUNT:
+ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+ __func__, port->number,
+ tport->tp_icount.rx, tport->tp_icount.tx);
+ if (copy_to_user((void __user *)arg, &tport->tp_icount,
+ sizeof(tport->tp_icount)))
+ return -EFAULT;
+ return 0;
}
-
return -ENOIOCTLCMD;
}
-static void ti_set_termios(struct usb_serial_port *port,
- struct ktermios *old_termios)
+static void ti_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
struct ti_port *tport = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
struct ti_uart_config *config;
- tcflag_t cflag,iflag;
+ tcflag_t cflag, iflag;
int baud;
int status;
int port_number = port->number - port->serial->minor;
@@ -893,7 +908,8 @@ static void ti_set_termios(struct usb_serial_port *port,
iflag = tty->termios->c_iflag;
dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
- dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
+ dbg("%s - old clfag %08x, old iflag %08x", __func__,
+ old_termios->c_cflag, old_termios->c_iflag);
if (tport == NULL)
return;
@@ -912,19 +928,19 @@ static void ti_set_termios(struct usb_serial_port *port,
config->bUartMode = (__u8)(tport->tp_uart_mode);
switch (cflag & CSIZE) {
- case CS5:
- config->bDataBits = TI_UART_5_DATA_BITS;
- break;
- case CS6:
- config->bDataBits = TI_UART_6_DATA_BITS;
- break;
- case CS7:
- config->bDataBits = TI_UART_7_DATA_BITS;
- break;
- default:
- case CS8:
- config->bDataBits = TI_UART_8_DATA_BITS;
- break;
+ case CS5:
+ config->bDataBits = TI_UART_5_DATA_BITS;
+ break;
+ case CS6:
+ config->bDataBits = TI_UART_6_DATA_BITS;
+ break;
+ case CS7:
+ config->bDataBits = TI_UART_7_DATA_BITS;
+ break;
+ default:
+ case CS8:
+ config->bDataBits = TI_UART_8_DATA_BITS;
+ break;
}
/* CMSPAR isn't supported by this driver */
@@ -940,7 +956,7 @@ static void ti_set_termios(struct usb_serial_port *port,
}
} else {
config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING;
- config->bParity = TI_UART_NO_PARITY;
+ config->bParity = TI_UART_NO_PARITY;
}
if (cflag & CSTOPB)
@@ -993,7 +1009,8 @@ static void ti_set_termios(struct usb_serial_port *port,
(__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
sizeof(*config));
if (status)
- dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
+ dev_err(&port->dev, "%s - cannot set config on port %d, %d\n",
+ __func__, port_number, status);
/* SET_CONFIG asserts RTS and DTR, reset them correctly */
mcr = tport->tp_shadow_mcr;
@@ -1002,14 +1019,17 @@ static void ti_set_termios(struct usb_serial_port *port,
mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
status = ti_set_mcr(tport, mcr);
if (status)
- dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
+ dev_err(&port->dev,
+ "%s - cannot set modem control on port %d, %d\n",
+ __func__, port_number, status);
kfree(config);
}
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ti_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned int result;
unsigned int msr;
@@ -1040,9 +1060,10 @@ static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
}
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned int mcr;
unsigned long flags;
@@ -1074,8 +1095,9 @@ static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
}
-static void ti_break(struct usb_serial_port *port, int break_state)
+static void ti_break(struct tty_struct *tty, int break_state)
{
+ struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
int status;
@@ -1141,10 +1163,12 @@ static void ti_interrupt_callback(struct urb *urb)
port_number = TI_GET_PORT_FROM_CODE(data[0]);
function = TI_GET_FUNC_FROM_CODE(data[0]);
- dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
+ dbg("%s - port_number %d, function %d, data 0x%02X",
+ __func__, port_number, function, data[1]);
if (port_number >= serial->num_ports) {
- dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
+ dev_err(dev, "%s - bad port number, %d\n",
+ __func__, port_number);
goto exit;
}
@@ -1156,7 +1180,8 @@ static void ti_interrupt_callback(struct urb *urb)
switch (function) {
case TI_CODE_DATA_ERROR:
- dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
+ dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n",
+ __func__, port_number, data[1]);
break;
case TI_CODE_MODEM_STATUS:
@@ -1166,7 +1191,8 @@ static void ti_interrupt_callback(struct urb *urb)
break;
default:
- dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
+ dev_err(dev, "%s - unknown interrupt code, 0x%02X\n",
+ __func__, data[1]);
break;
}
@@ -1200,7 +1226,7 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
default:
dev_err(dev, "%s - nonzero urb status, %d\n",
- __func__, status );
+ __func__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
}
@@ -1213,15 +1239,16 @@ static void ti_bulk_in_callback(struct urb *urb)
return;
}
- if (port->tty && urb->actual_length) {
+ if (port->port.tty && urb->actual_length) {
usb_serial_debug_data(debug, dev, __func__,
urb->actual_length, urb->transfer_buffer);
if (!tport->tp_is_open)
dbg("%s - port closed, dropping data", __func__);
else
- ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
- urb->actual_length);
+ ti_recv(&urb->dev->dev, port->port.tty,
+ urb->transfer_buffer,
+ urb->actual_length);
spin_lock(&tport->tp_lock);
tport->tp_icount.rx += urb->actual_length;
@@ -1285,8 +1312,9 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
do {
cnt = tty_buffer_request_room(tty, length);
if (cnt < length) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
- if(cnt == 0)
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __func__, length - cnt);
+ if (cnt == 0)
break;
}
tty_insert_flip_string(tty, data, cnt);
@@ -1302,7 +1330,7 @@ static void ti_send(struct ti_port *tport)
{
int count, result;
struct usb_serial_port *port = tport->tp_port;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty; /* FIXME */
unsigned long flags;
@@ -1328,7 +1356,8 @@ static void ti_send(struct ti_port *tport)
spin_unlock_irqrestore(&tport->tp_lock, flags);
- usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev, __func__, count,
+ port->write_urb->transfer_buffer);
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
@@ -1338,8 +1367,9 @@ static void ti_send(struct ti_port *tport)
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
- tport->tp_write_urb_in_use = 0;
+ dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+ __func__, result);
+ tport->tp_write_urb_in_use = 0;
/* TODO: reschedule ti_send */
} else {
spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1374,7 +1404,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
static int ti_get_lsr(struct ti_port *tport)
{
- int size,status;
+ int size, status;
struct ti_device *tdev = tport->tp_tdev;
struct usb_serial_port *port = tport->tp_port;
int port_number = port->number - port->serial->minor;
@@ -1392,7 +1422,9 @@ static int ti_get_lsr(struct ti_port *tport)
status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
if (status) {
- dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
+ dev_err(&port->dev,
+ "%s - get port status command failed, %d\n",
+ __func__, status);
goto free_data;
}
@@ -1442,8 +1474,9 @@ static int ti_set_serial_info(struct ti_port *tport,
return -EFAULT;
tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
- if (port->tty)
- port->tty->low_latency =
+ /* FIXME */
+ if (port->port.tty)
+ port->port.tty->low_latency =
(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
tport->tp_closing_wait = new_serial.closing_wait;
@@ -1477,7 +1510,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
tport->tp_msr = msr & TI_MSR_MASK;
/* handle CTS flow control */
- tty = tport->tp_port->tty;
+ tty = tport->tp_port->port.tty;
if (tty && C_CRTSCTS(tty)) {
if (msr & TI_MSR_CTS) {
tty->hw_stopped = 0;
@@ -1627,7 +1660,8 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
struct ti_write_data_bytes *data;
struct device *dev = &tdev->td_serial->dev->dev;
- dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
+ dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X",
+ __func__, addr, mask, byte);
size = sizeof(struct ti_write_data_bytes) + 2;
data = kmalloc(size, GFP_KERNEL);
@@ -1655,67 +1689,68 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
return status;
}
-
-static int ti_download_firmware(struct ti_device *tdev,
- char *fw_name)
+static int ti_do_download(struct usb_device *dev, int pipe,
+ u8 *buffer, int size)
{
- const struct firmware *fw;
- int status = 0;
- int buffer_size;
int pos;
- int len;
+ u8 cs = 0;
int done;
- __u8 cs = 0;
- __u8 *buffer;
- struct usb_device *dev = tdev->td_serial->dev;
struct ti_firmware_header *header;
- unsigned int pipe = usb_sndbulkpipe(dev,
- tdev->td_serial->port[0]->bulk_out_endpointAddress);
-
- buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
-
- if (request_firmware(&fw, fw_name, &dev->dev)) {
- dev_err(&dev->dev, "%s - failed to load firmware \"%s\"\n",
- __func__, fw_name);
- return -ENOENT;
- }
- if (fw->size > buffer_size) {
- dev_err(&dev->dev, "%s - firmware \"%s\" is too large\n",
- __func__, fw_name);
- release_firmware(fw);
- return -EINVAL;
- }
-
- buffer = kmalloc(buffer_size, GFP_KERNEL);
- if (!buffer) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- release_firmware(fw);
- return -ENOMEM;
- }
-
- memcpy(buffer, fw->data, fw->size);
- memset(buffer+fw->size, 0xff, buffer_size-fw->size);
+ int status;
+ int len;
- for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++)
+ for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
cs = (__u8)(cs + buffer[pos]);
header = (struct ti_firmware_header *)buffer;
- header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+ header->wLength = cpu_to_le16((__u16)(size
+ - sizeof(struct ti_firmware_header)));
header->bCheckSum = cs;
dbg("%s - downloading firmware", __func__);
- for (pos = 0; pos < buffer_size; pos += done) {
- len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
- status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
+ for (pos = 0; pos < size; pos += done) {
+ len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+ status = usb_bulk_msg(dev, pipe, buffer + pos, len,
+ &done, 1000);
if (status)
break;
}
+ return status;
+}
- kfree(buffer);
- release_firmware(fw);
+static int ti_download_firmware(struct ti_device *tdev, int type)
+{
+ int status = -ENOMEM;
+ int buffer_size;
+ __u8 *buffer;
+ struct usb_device *dev = tdev->td_serial->dev;
+ unsigned int pipe = usb_sndbulkpipe(dev,
+ tdev->td_serial->port[0]->bulk_out_endpointAddress);
+ const struct firmware *fw_p;
+ char buf[32];
+ sprintf(buf, "ti_usb-%d.bin", type);
+ if (request_firmware(&fw_p, buf, &dev->dev)) {
+ dev_err(&dev->dev, "%s - firmware not found\n", __func__);
+ return -ENOENT;
+ }
+ if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
+ dev_err(&dev->dev, "%s - firmware too large\n", __func__);
+ return -ENOENT;
+ }
+
+ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (buffer) {
+ memcpy(buffer, fw_p->data, fw_p->size);
+ memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
+ ti_do_download(dev, pipe, buffer, fw_p->size);
+ kfree(buffer);
+ }
+ release_firmware(fw_p);
if (status) {
- dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+ dev_err(&dev->dev, "%s - error downloading firmware, %d\n",
+ __func__, status);
return status;
}
@@ -1787,7 +1822,7 @@ static void ti_buf_clear(struct circ_buf *cb)
static int ti_buf_data_avail(struct circ_buf *cb)
{
- return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+ return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
@@ -1800,7 +1835,7 @@ static int ti_buf_data_avail(struct circ_buf *cb)
static int ti_buf_space_avail(struct circ_buf *cb)
{
- return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+ return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0cb0d77dc42..8c2d531eede 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -12,7 +12,8 @@
* This driver was originally based on the ACM driver by Armin Fuerst (which was
* based on a driver by Brad Keryan)
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -28,7 +29,7 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/list.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "pl2303.h"
@@ -59,7 +60,8 @@ static struct usb_driver usb_serial_driver = {
*/
static int debug;
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
+/* initially all NULL */
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list);
@@ -76,7 +78,8 @@ struct usb_serial *usb_serial_get_by_index(unsigned index)
return serial;
}
-static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor)
+static struct usb_serial *get_free_serial(struct usb_serial *serial,
+ int num_ports, unsigned int *minor)
{
unsigned int i, j;
int good_spot;
@@ -122,9 +125,8 @@ static void return_serial(struct usb_serial *serial)
if (serial == NULL)
return;
- for (i = 0; i < serial->num_ports; ++i) {
+ for (i = 0; i < serial->num_ports; ++i)
serial_table[serial->minor + i] = NULL;
- }
}
static void destroy_serial(struct kref *kref)
@@ -143,7 +145,7 @@ static void destroy_serial(struct kref *kref)
return_serial(serial);
for (i = 0; i < serial->num_ports; ++i)
- serial->port[i]->open_count = 0;
+ serial->port[i]->port.count = 0;
/* the ports are cleaned up and released in port_release() */
for (i = 0; i < serial->num_ports; ++i)
@@ -156,7 +158,8 @@ static void destroy_serial(struct kref *kref)
* not get cleaned up in port_release() as it was never registered with
* the driver core */
if (serial->num_ports < serial->num_port_pointers) {
- for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+ for (i = serial->num_ports;
+ i < serial->num_port_pointers; ++i) {
port = serial->port[i];
if (!port)
continue;
@@ -167,7 +170,7 @@ static void destroy_serial(struct kref *kref)
usb_put_dev(serial->dev);
/* free up any memory that we allocated */
- kfree (serial);
+ kfree(serial);
}
void usb_serial_put(struct usb_serial *serial)
@@ -180,13 +183,13 @@ void usb_serial_put(struct usb_serial *serial)
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
-static int serial_open (struct tty_struct *tty, struct file * filp)
+static int serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
unsigned int portNumber;
int retval;
-
+
dbg("%s", __func__);
/* get the serial object associated with this tty pointer */
@@ -207,15 +210,15 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
retval = -ERESTARTSYS;
goto bailout_kref_put;
}
-
- ++port->open_count;
+
+ ++port->port.count;
/* set up our port structure making the tty driver
* remember our port object, and us it */
tty->driver_data = port;
- port->tty = tty;
+ port->port.tty = tty;
- if (port->open_count == 1) {
+ if (port->port.count == 1) {
/* lock this module before we call it
* this may fail, which means we must bail out,
@@ -228,9 +231,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
retval = usb_autopm_get_interface(serial->interface);
if (retval)
goto bailout_module_put;
- /* only call the device specific open if this
+ /* only call the device specific open if this
* is the first time the port is opened */
- retval = serial->type->open(port, filp);
+ retval = serial->type->open(tty, port, filp);
if (retval)
goto bailout_interface_put;
}
@@ -243,16 +246,16 @@ bailout_interface_put:
bailout_module_put:
module_put(serial->type->driver.owner);
bailout_mutex_unlock:
- port->open_count = 0;
+ port->port.count = 0;
tty->driver_data = NULL;
- port->tty = NULL;
+ port->port.tty = NULL;
mutex_unlock(&port->mutex);
bailout_kref_put:
usb_serial_put(serial);
return retval;
}
-static void serial_close(struct tty_struct *tty, struct file * filp)
+static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
@@ -263,27 +266,30 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
mutex_lock(&port->mutex);
- if (port->open_count == 0) {
+ if (port->port.count == 0) {
mutex_unlock(&port->mutex);
return;
}
- --port->open_count;
- if (port->open_count == 0)
- /* only call the device specific close if this
+ --port->port.count;
+ if (port->port.count == 0)
+ /* only call the device specific close if this
* port is being closed by the last owner */
- port->serial->type->close(port, filp);
+ port->serial->type->close(tty, port, filp);
- if (port->open_count == (port->console? 1 : 0)) {
- if (port->tty) {
- if (port->tty->driver_data)
- port->tty->driver_data = NULL;
- port->tty = NULL;
+ if (port->port.count == (port->console? 1 : 0)) {
+ if (port->port.tty) {
+ if (port->port.tty->driver_data)
+ port->port.tty->driver_data = NULL;
+ port->port.tty = NULL;
}
}
- if (port->open_count == 0) {
- usb_autopm_put_interface(port->serial->interface);
+ if (port->port.count == 0) {
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected)
+ usb_autopm_put_interface(port->serial->interface);
+ mutex_unlock(&port->serial->disc_mutex);
module_put(port->serial->type->driver.owner);
}
@@ -291,7 +297,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
usb_serial_put(port->serial);
}
-static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
+static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
@@ -301,107 +308,112 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
- /* open_count is managed under the mutex lock for the tty so cannot
- drop to zero until after the last close completes */
- WARN_ON(!port->open_count);
+ /* count is managed under the mutex lock for the tty so cannot
+ drop to zero until after the last close completes */
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- retval = port->serial->type->write(port, buf, count);
+ retval = port->serial->type->write(tty, port, buf, count);
exit:
return retval;
}
-static int serial_write_room (struct tty_struct *tty)
+static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- return port->serial->type->write_room(port);
+ return port->serial->type->write_room(tty);
}
-static int serial_chars_in_buffer (struct tty_struct *tty)
+static int serial_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s = port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
- return port->serial->type->chars_in_buffer(port);
+ return port->serial->type->chars_in_buffer(tty);
}
-static void serial_throttle (struct tty_struct * tty)
+static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
if (port->serial->type->throttle)
- port->serial->type->throttle(port);
+ port->serial->type->throttle(tty);
}
-static void serial_unthrottle (struct tty_struct * tty)
+static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
/* pass on to the driver specific version of this function */
if (port->serial->type->unthrottle)
- port->serial->type->unthrottle(port);
+ port->serial->type->unthrottle(tty);
}
-static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serial_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
- /* pass on to the driver specific version of this function if it is available */
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->ioctl) {
lock_kernel();
- retval = port->serial->type->ioctl(port, file, cmd, arg);
+ retval = port->serial->type->ioctl(tty, file, cmd, arg);
unlock_kernel();
- }
- else
+ } else
retval = -ENOIOCTLCMD;
return retval;
}
-static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
- /* pass on to the driver specific version of this function if it is available */
+ WARN_ON(!port->port.count);
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->set_termios)
- port->serial->type->set_termios(port, old);
+ port->serial->type->set_termios(tty, port, old);
else
tty_termios_copy_hw(tty->termios, old);
}
-static void serial_break (struct tty_struct *tty, int break_state)
+static int serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
- /* pass on to the driver specific version of this function if it is available */
+ WARN_ON(!port->port.count);
+ /* pass on to the driver specific version of this function
+ if it is available */
if (port->serial->type->break_ctl) {
lock_kernel();
- port->serial->type->break_ctl(port, break_state);
+ port->serial->type->break_ctl(tty, break_state);
unlock_kernel();
}
+ return 0;
}
-static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int serial_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
{
struct usb_serial *serial;
int length = 0;
@@ -410,26 +422,29 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
char tmp[40];
dbg("%s", __func__);
- length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
+ length += sprintf(page, "usbserinfo:1.0 driver:2.0\n");
for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
serial = usb_serial_get_by_index(i);
if (serial == NULL)
continue;
- length += sprintf (page+length, "%d:", i);
+ length += sprintf(page+length, "%d:", i);
if (serial->type->driver.owner)
- length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
- length += sprintf (page+length, " name:\"%s\"", serial->type->description);
- length += sprintf (page+length, " vendor:%04x product:%04x",
- le16_to_cpu(serial->dev->descriptor.idVendor),
- le16_to_cpu(serial->dev->descriptor.idProduct));
- length += sprintf (page+length, " num_ports:%d", serial->num_ports);
- length += sprintf (page+length, " port:%d", i - serial->minor + 1);
-
+ length += sprintf(page+length, " module:%s",
+ module_name(serial->type->driver.owner));
+ length += sprintf(page+length, " name:\"%s\"",
+ serial->type->description);
+ length += sprintf(page+length, " vendor:%04x product:%04x",
+ le16_to_cpu(serial->dev->descriptor.idVendor),
+ le16_to_cpu(serial->dev->descriptor.idProduct));
+ length += sprintf(page+length, " num_ports:%d",
+ serial->num_ports);
+ length += sprintf(page+length, " port:%d",
+ i - serial->minor + 1);
usb_make_path(serial->dev, tmp, sizeof(tmp));
- length += sprintf (page+length, " path:%s", tmp);
-
- length += sprintf (page+length, "\n");
+ length += sprintf(page+length, " path:%s", tmp);
+
+ length += sprintf(page+length, "\n");
if ((length + begin) > (off + count)) {
usb_serial_put(serial);
goto done;
@@ -445,31 +460,31 @@ done:
if (off >= (length + begin))
return 0;
*start = page + (off-begin);
- return ((count < begin+length-off) ? count : begin+length-off);
+ return (count < begin+length-off) ? count : begin+length-off;
}
-static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+static int serial_tiocmget(struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
if (port->serial->type->tiocmget)
- return port->serial->type->tiocmget(port, file);
+ return port->serial->type->tiocmget(tty, file);
return -EINVAL;
}
-static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+static int serial_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s - port %d", __func__, port->number);
- WARN_ON(!port->open_count);
+ WARN_ON(!port->port.count);
if (port->serial->type->tiocmset)
- return port->serial->type->tiocmset(port, file, set, clear);
+ return port->serial->type->tiocmset(tty, file, set, clear);
return -EINVAL;
}
@@ -482,6 +497,7 @@ void usb_serial_port_softint(struct usb_serial_port *port)
{
schedule_work(&port->work);
}
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
static void usb_serial_port_work(struct work_struct *work)
{
@@ -490,11 +506,11 @@ static void usb_serial_port_work(struct work_struct *work)
struct tty_struct *tty;
dbg("%s - port %d", __func__, port->number);
-
+
if (!port)
return;
- tty = port->tty;
+ tty = port->port.tty;
if (!tty)
return;
@@ -505,7 +521,7 @@ static void port_release(struct device *dev)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
- dbg ("%s - %s", __func__, dev->bus_id);
+ dbg ("%s - %s", __func__, dev_name(dev));
port_free(port);
}
@@ -543,9 +559,9 @@ static void port_free(struct usb_serial_port *port)
kfree(port);
}
-static struct usb_serial * create_serial (struct usb_device *dev,
- struct usb_interface *interface,
- struct usb_serial_driver *driver)
+static struct usb_serial *create_serial(struct usb_device *dev,
+ struct usb_interface *interface,
+ struct usb_serial_driver *driver)
{
struct usb_serial *serial;
@@ -564,7 +580,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
}
static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
- struct usb_serial_driver *drv)
+ struct usb_serial_driver *drv)
{
struct usb_dynid *dynid;
@@ -596,7 +612,8 @@ exit:
return id;
}
-static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(
+ struct usb_interface *iface)
{
const struct usb_device_id *id;
struct usb_serial_driver *drv;
@@ -614,7 +631,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac
int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
- struct usb_device *dev = interface_to_usbdev (interface);
+ struct usb_device *dev = interface_to_usbdev(interface);
struct usb_serial *serial = NULL;
struct usb_serial_port *port;
struct usb_host_interface *iface_desc;
@@ -625,7 +642,7 @@ int usb_serial_probe(struct usb_interface *interface,
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_driver *type = NULL;
int retval;
- int minor;
+ unsigned int minor;
int buffer_size;
int i;
int num_interrupt_in = 0;
@@ -643,7 +660,7 @@ int usb_serial_probe(struct usb_interface *interface,
return -ENODEV;
}
- serial = create_serial (dev, interface, type);
+ serial = create_serial(dev, interface, type);
if (!serial) {
unlock_kernel();
dev_err(&interface->dev, "%s - out of memory\n", __func__);
@@ -656,8 +673,9 @@ int usb_serial_probe(struct usb_interface *interface,
if (!try_module_get(type->driver.owner)) {
unlock_kernel();
- dev_err(&interface->dev, "module get failed, exiting\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
+ kfree(serial);
return -EIO;
}
@@ -667,8 +685,8 @@ int usb_serial_probe(struct usb_interface *interface,
if (retval) {
unlock_kernel();
- dbg ("sub driver rejected device");
- kfree (serial);
+ dbg("sub driver rejected device");
+ kfree(serial);
return retval;
}
}
@@ -709,7 +727,7 @@ int usb_serial_probe(struct usb_interface *interface,
}
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
- /* BEGIN HORRIBLE HACK FOR PL2303 */
+ /* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
@@ -738,7 +756,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (num_bulk_in == 0 || num_bulk_out == 0) {
unlock_kernel();
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
- kfree (serial);
+ kfree(serial);
return -ENODEV;
}
}
@@ -750,8 +768,9 @@ int usb_serial_probe(struct usb_interface *interface,
num_ports = num_bulk_out;
if (num_ports == 0) {
unlock_kernel();
- dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "Generic device with no bulk out, not allowed.\n");
+ kfree(serial);
return -EIO;
}
}
@@ -761,11 +780,12 @@ int usb_serial_probe(struct usb_interface *interface,
if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) {
unlock_kernel();
- dev_err(&interface->dev, "module get failed, exiting\n");
- kfree (serial);
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
+ kfree(serial);
return -EIO;
}
- num_ports = type->calc_num_ports (serial);
+ num_ports = type->calc_num_ports(serial);
module_put(type->driver.owner);
}
if (!num_ports)
@@ -783,7 +803,8 @@ int usb_serial_probe(struct usb_interface *interface,
type->description);
/* create our ports, we need as many as the max endpoints */
- /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
+ /* we don't use num_ports here because some devices have more
+ endpoint pairs than ports */
max_endpoints = max(num_bulk_in, num_bulk_out);
max_endpoints = max(max_endpoints, num_interrupt_in);
max_endpoints = max(max_endpoints, num_interrupt_out);
@@ -791,7 +812,8 @@ int usb_serial_probe(struct usb_interface *interface,
serial->num_port_pointers = max_endpoints;
unlock_kernel();
- dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
+ dbg("%s - setting up %d port structures for this device",
+ __func__, max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
if (!port)
@@ -807,7 +829,7 @@ int usb_serial_probe(struct usb_interface *interface,
for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i];
port = serial->port[i];
- port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
+ port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->read_urb) {
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
@@ -815,17 +837,17 @@ int usb_serial_probe(struct usb_interface *interface,
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_in_size = buffer_size;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!port->bulk_in_buffer) {
- dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate bulk_in_buffer\n");
goto probe_error;
}
- usb_fill_bulk_urb (port->read_urb, dev,
- usb_rcvbulkpipe (dev,
- endpoint->bEndpointAddress),
- port->bulk_in_buffer, buffer_size,
- serial->type->read_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->read_urb, dev,
+ usb_rcvbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size,
+ serial->type->read_bulk_callback, port);
}
for (i = 0; i < num_bulk_out; ++i) {
@@ -839,17 +861,17 @@ int usb_serial_probe(struct usb_interface *interface,
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_out_size = buffer_size;
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
- port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
if (!port->bulk_out_buffer) {
- dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate bulk_out_buffer\n");
goto probe_error;
}
- usb_fill_bulk_urb (port->write_urb, dev,
- usb_sndbulkpipe (dev,
- endpoint->bEndpointAddress),
- port->bulk_out_buffer, buffer_size,
- serial->type->write_bulk_callback,
- port);
+ usb_fill_bulk_urb(port->write_urb, dev,
+ usb_sndbulkpipe(dev,
+ endpoint->bEndpointAddress),
+ port->bulk_out_buffer, buffer_size,
+ serial->type->write_bulk_callback, port);
}
if (serial->type->read_int_callback) {
@@ -858,73 +880,82 @@ int usb_serial_probe(struct usb_interface *interface,
port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
+ dev_err(&interface->dev,
+ "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
- port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
- port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->interrupt_in_endpointAddress =
+ endpoint->bEndpointAddress;
+ port->interrupt_in_buffer = kmalloc(buffer_size,
+ GFP_KERNEL);
if (!port->interrupt_in_buffer) {
- dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate interrupt_in_buffer\n");
goto probe_error;
}
- usb_fill_int_urb (port->interrupt_in_urb, dev,
- usb_rcvintpipe (dev,
- endpoint->bEndpointAddress),
- port->interrupt_in_buffer, buffer_size,
- serial->type->read_int_callback, port,
- endpoint->bInterval);
+ usb_fill_int_urb(port->interrupt_in_urb, dev,
+ usb_rcvintpipe(dev,
+ endpoint->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size,
+ serial->type->read_int_callback, port,
+ endpoint->bInterval);
}
} else if (num_interrupt_in) {
dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
}
-
+
if (serial->type->write_int_callback) {
for (i = 0; i < num_interrupt_out; ++i) {
endpoint = interrupt_out_endpoint[i];
port = serial->port[i];
port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_out_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
+ dev_err(&interface->dev,
+ "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->interrupt_out_size = buffer_size;
- port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
- port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ port->interrupt_out_endpointAddress =
+ endpoint->bEndpointAddress;
+ port->interrupt_out_buffer = kmalloc(buffer_size,
+ GFP_KERNEL);
if (!port->interrupt_out_buffer) {
- dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+ dev_err(&interface->dev,
+ "Couldn't allocate interrupt_out_buffer\n");
goto probe_error;
}
- usb_fill_int_urb (port->interrupt_out_urb, dev,
- usb_sndintpipe (dev,
- endpoint->bEndpointAddress),
- port->interrupt_out_buffer, buffer_size,
- serial->type->write_int_callback, port,
- endpoint->bInterval);
+ usb_fill_int_urb(port->interrupt_out_urb, dev,
+ usb_sndintpipe(dev,
+ endpoint->bEndpointAddress),
+ port->interrupt_out_buffer, buffer_size,
+ serial->type->write_int_callback, port,
+ endpoint->bInterval);
}
} else if (num_interrupt_out) {
dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
}
-
+
/* if this device type has an attach function, call it */
if (type->attach) {
if (!try_module_get(type->driver.owner)) {
- dev_err(&interface->dev, "module get failed, exiting\n");
+ dev_err(&interface->dev,
+ "module get failed, exiting\n");
goto probe_error;
}
- retval = type->attach (serial);
+ retval = type->attach(serial);
module_put(type->driver.owner);
if (retval < 0)
goto probe_error;
if (retval > 0) {
- /* quietly accept this device, but don't bind to a serial port
- * as it's about to disappear */
+ /* quietly accept this device, but don't bind to a
+ serial port as it's about to disappear */
goto exit;
}
}
- if (get_free_serial (serial, num_ports, &minor) == NULL) {
+ if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error;
}
@@ -938,19 +969,19 @@ int usb_serial_probe(struct usb_interface *interface,
port->dev.bus = &usb_serial_bus_type;
port->dev.release = &port_release;
- snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
- dbg ("%s - registering %s", __func__, port->dev.bus_id);
+ dev_set_name(&port->dev, "ttyUSB%d", port->number);
+ dbg ("%s - registering %s", __func__, dev_name(&port->dev));
retval = device_register(&port->dev);
if (retval)
dev_err(&port->dev, "Error registering port device, "
"continuing\n");
}
- usb_serial_console_init (debug, minor);
+ usb_serial_console_init(debug, minor);
exit:
/* success */
- usb_set_intfdata (interface, serial);
+ usb_set_intfdata(interface, serial);
return 0;
probe_error:
@@ -986,29 +1017,30 @@ probe_error:
/* free up any memory that we allocated */
for (i = 0; i < serial->num_port_pointers; ++i)
kfree(serial->port[i]);
- kfree (serial);
+ kfree(serial);
return -EIO;
}
+EXPORT_SYMBOL_GPL(usb_serial_probe);
void usb_serial_disconnect(struct usb_interface *interface)
{
int i;
- struct usb_serial *serial = usb_get_intfdata (interface);
+ struct usb_serial *serial = usb_get_intfdata(interface);
struct device *dev = &interface->dev;
struct usb_serial_port *port;
usb_serial_console_disconnect(serial);
- dbg ("%s", __func__);
+ dbg("%s", __func__);
mutex_lock(&serial->disc_mutex);
- usb_set_intfdata (interface, NULL);
+ usb_set_intfdata(interface, NULL);
/* must set a flag, to signal subdrivers */
serial->disconnected = 1;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port) {
- if (port->tty)
- tty_hangup(port->tty);
+ if (port->port.tty)
+ tty_hangup(port->port.tty);
kill_traffic(port);
}
}
@@ -1018,6 +1050,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
{
@@ -1076,9 +1109,8 @@ static int __init usb_serial_init(void)
return -ENOMEM;
/* Initialize our global data */
- for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+ for (i = 0; i < SERIAL_TTY_MINORS; ++i)
serial_table[i] = NULL;
- }
result = bus_register(&usb_serial_bus_type);
if (result) {
@@ -1093,9 +1125,11 @@ static int __init usb_serial_init(void)
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
- usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
+ | HUPCL | CLOCAL;
usb_serial_tty_driver->init_termios.c_ispeed = 9600;
usb_serial_tty_driver->init_termios.c_ospeed = 9600;
tty_set_operations(usb_serial_tty_driver, &serial_ops);
@@ -1133,7 +1167,7 @@ exit_reg_driver:
bus_unregister(&usb_serial_bus_type);
exit_bus:
- err ("%s - returning with error %d", __func__, result);
+ err("%s - returning with error %d", __func__, result);
put_tty_driver(usb_serial_tty_driver);
return result;
}
@@ -1160,7 +1194,7 @@ module_exit(usb_serial_exit);
if (!type->function) { \
type->function = usb_serial_generic_##function; \
dbg("Had to override the " #function \
- " usb serial operation with the generic one.");\
+ " usb serial operation with the generic one.");\
} \
} while (0)
@@ -1177,8 +1211,9 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, resume);
}
-int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
+int usb_serial_register(struct usb_serial_driver *driver)
{
+ /* must be called with BKL held */
int retval;
fixup_generic(driver);
@@ -1191,37 +1226,30 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with
retval = usb_serial_bus_register(driver);
if (retval) {
- err("problem %d when registering driver %s", retval, driver->description);
+ err("problem %d when registering driver %s",
+ retval, driver->description);
list_del(&driver->driver_list);
- }
- else
- info("USB Serial support registered for %s", driver->description);
+ } else
+ info("USB Serial support registered for %s",
+ driver->description);
return retval;
}
+EXPORT_SYMBOL_GPL(usb_serial_register);
-void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
+void usb_serial_deregister(struct usb_serial_driver *device)
{
+ /* must be called with BKL held */
info("USB Serial deregistering driver %s", device->description);
list_del(&device->driver_list);
usb_serial_bus_deregister(device);
}
-
-
-
-/* If the usb-serial core is built into the core, the usb-serial drivers
- need these symbols to load properly as modules. */
-EXPORT_SYMBOL_GPL(usb_serial_register);
EXPORT_SYMBOL_GPL(usb_serial_deregister);
-EXPORT_SYMBOL_GPL(usb_serial_probe);
-EXPORT_SYMBOL_GPL(usb_serial_disconnect);
-EXPORT_SYMBOL_GPL(usb_serial_port_softint);
-
/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index f9fc926b56d..fc5d9952b03 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -15,6 +15,8 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#define USB_DEBUG_MAX_PACKET_SIZE 8
+
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0525, 0x127a) },
{ },
@@ -29,6 +31,13 @@ static struct usb_driver debug_driver = {
.no_dynamic_id = 1,
};
+int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
+{
+ port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE;
+ return usb_serial_generic_open(tty, port, filp);
+}
+
static struct usb_serial_driver debug_device = {
.driver = {
.owner = THIS_MODULE,
@@ -36,6 +45,7 @@ static struct usb_serial_driver debug_device = {
},
.id_table = id_table,
.num_ports = 1,
+ .open = usb_debug_open,
};
static int __init debug_init(void)
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 5fc20122145..cf8924f9a2c 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -9,7 +9,8 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -23,7 +24,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include "visor.h"
@@ -35,25 +36,29 @@
#define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
/* function prototypes for a handspring visor */
-static int visor_open (struct usb_serial_port *port, struct file *filp);
-static void visor_close (struct usb_serial_port *port, struct file *filp);
-static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int visor_write_room (struct usb_serial_port *port);
-static int visor_chars_in_buffer (struct usb_serial_port *port);
-static void visor_throttle (struct usb_serial_port *port);
-static void visor_unthrottle (struct usb_serial_port *port);
-static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id);
+static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp);
+static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int visor_write_room(struct tty_struct *tty);
+static void visor_throttle(struct tty_struct *tty);
+static void visor_unthrottle(struct tty_struct *tty);
+static int visor_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
static int visor_calc_num_ports(struct usb_serial *serial);
-static void visor_shutdown (struct usb_serial *serial);
-static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_write_bulk_callback (struct urb *urb);
-static void visor_read_bulk_callback (struct urb *urb);
-static void visor_read_int_callback (struct urb *urb);
-static int clie_3_5_startup (struct usb_serial *serial);
-static int treo_attach (struct usb_serial *serial);
-static int clie_5_attach (struct usb_serial *serial);
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id);
+static void visor_shutdown(struct usb_serial *serial);
+static void visor_write_bulk_callback(struct urb *urb);
+static void visor_read_bulk_callback(struct urb *urb);
+static void visor_read_int_callback(struct urb *urb);
+static int clie_3_5_startup(struct usb_serial *serial);
+static int treo_attach(struct usb_serial *serial);
+static int clie_5_attach(struct usb_serial *serial);
+static int palm_os_3_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static int palm_os_4_probe(struct usb_serial *serial,
+ const struct usb_device_id *id);
/* Parameters that may be passed into the module. */
static int debug;
@@ -105,13 +110,13 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
+ { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
@@ -170,7 +175,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver visor_driver = {
.name = "visor",
@@ -180,7 +185,8 @@ static struct usb_driver visor_driver = {
.no_dynamic_id = 1,
};
-/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
+/* All of the device info needed for the Handspring Visor,
+ and Palm 4.0 devices */
static struct usb_serial_driver handspring_device = {
.driver = {
.owner = THIS_MODULE,
@@ -198,10 +204,8 @@ static struct usb_serial_driver handspring_device = {
.probe = visor_probe,
.calc_num_ports = visor_calc_num_ports,
.shutdown = visor_shutdown,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
.read_int_callback = visor_read_int_callback,
@@ -225,10 +229,8 @@ static struct usb_serial_driver clie_5_device = {
.probe = visor_probe,
.calc_num_ports = visor_calc_num_ports,
.shutdown = visor_shutdown,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
.read_int_callback = visor_read_int_callback,
@@ -249,10 +251,8 @@ static struct usb_serial_driver clie_3_5_device = {
.throttle = visor_throttle,
.unthrottle = visor_unthrottle,
.attach = clie_3_5_startup,
- .ioctl = visor_ioctl,
.write = visor_write,
.write_room = visor_write_room,
- .chars_in_buffer = visor_chars_in_buffer,
.write_bulk_callback = visor_write_bulk_callback,
.read_bulk_callback = visor_read_bulk_callback,
};
@@ -274,7 +274,8 @@ static int stats;
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
-static int visor_open (struct usb_serial_port *port, struct file *filp)
+static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+ struct file *filp)
{
struct usb_serial *serial = port->serial;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -300,42 +301,45 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
* through, otherwise it is scheduled, and with high data rates (like
* with OHCI) data can get lost.
*/
- if (port->tty)
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* Start reading from the device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
- usb_rcvbulkpipe (serial->dev,
+ usb_fill_bulk_urb(port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) {
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
goto exit;
}
-
+
if (port->interrupt_in_urb) {
dbg("%s - adding interrupt input for treo", __func__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
- dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
- __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting interrupt urb, error %d\n",
+ __func__, result);
}
-exit:
+exit:
return result;
}
-static void visor_close (struct usb_serial_port *port, struct file * filp)
+static void visor_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
dbg("%s - port %d", __func__, port->number);
-
+
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
@@ -343,14 +347,14 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected) {
/* Try to send shutdown message, unless the device is gone */
- transfer_buffer = kmalloc (0x12, GFP_KERNEL);
+ transfer_buffer = kmalloc(0x12, GFP_KERNEL);
if (transfer_buffer) {
- usb_control_msg (port->serial->dev,
+ usb_control_msg(port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
}
}
mutex_unlock(&port->serial->disc_mutex);
@@ -361,7 +365,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
}
-static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
struct visor_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -381,7 +386,7 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
priv->outstanding_urbs++;
spin_unlock_irqrestore(&priv->lock, flags);
- buffer = kmalloc (count, GFP_ATOMIC);
+ buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
dev_err(&port->dev, "out of memory\n");
count = -ENOMEM;
@@ -395,21 +400,22 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
goto error_no_urb;
}
- memcpy (buffer, buf, count);
+ memcpy(buffer, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
- usb_fill_bulk_urb (urb, serial->dev,
- usb_sndbulkpipe (serial->dev,
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
port->bulk_out_endpointAddress),
- buffer, count,
+ buffer, count,
visor_write_bulk_callback, port);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
- __func__, status);
+ dev_err(&port->dev,
+ "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+ __func__, status);
count = status;
goto error;
} else {
@@ -435,8 +441,9 @@ error_no_buffer:
}
-static int visor_write_room (struct usb_serial_port *port)
+static int visor_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -460,23 +467,7 @@ static int visor_write_room (struct usb_serial_port *port)
}
-static int visor_chars_in_buffer (struct usb_serial_port *port)
-{
- dbg("%s - port %d", __func__, port->number);
-
- /*
- * We can't really account for how much data we
- * have sent out, but hasn't made it through to the
- * device, so just tell the tty layer that everything
- * is flushed.
- *
- * FIXME: Should walk outstanding_urbs
- */
- return 0;
-}
-
-
-static void visor_write_bulk_callback (struct urb *urb)
+static void visor_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -484,7 +475,7 @@ static void visor_write_bulk_callback (struct urb *urb)
unsigned long flags;
/* free up the transfer buffer, as usb_free_urb() does not do this */
- kfree (urb->transfer_buffer);
+ kfree(urb->transfer_buffer);
dbg("%s - port %d", __func__, port->number);
@@ -500,7 +491,7 @@ static void visor_write_bulk_callback (struct urb *urb)
}
-static void visor_read_bulk_callback (struct urb *urb)
+static void visor_read_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
@@ -518,11 +509,13 @@ static void visor_read_bulk_callback (struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, data);
- tty = port->tty;
+ tty = port->port.tty;
if (tty && urb->actual_length) {
- available_room = tty_buffer_request_room(tty, urb->actual_length);
+ available_room = tty_buffer_request_room(tty,
+ urb->actual_length);
if (available_room) {
tty_insert_flip_string(tty, data, available_room);
tty_flip_buffer_push(tty);
@@ -536,22 +529,23 @@ static void visor_read_bulk_callback (struct urb *urb)
/* Continue trying to always read if we should */
if (!priv->throttled) {
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
+ port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
- } else {
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __func__, result);
+ } else
priv->actually_throttled = 1;
- }
spin_unlock(&priv->lock);
}
-static void visor_read_int_callback (struct urb *urb)
+static void visor_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
@@ -585,14 +579,16 @@ static void visor_read_int_callback (struct urb *urb)
urb->actual_length, urb->transfer_buffer);
exit:
- result = usb_submit_urb (urb, GFP_ATOMIC);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
- __func__, result);
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+ __func__, result);
}
-static void visor_throttle (struct usb_serial_port *port)
+static void visor_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
@@ -603,8 +599,9 @@ static void visor_throttle (struct usb_serial_port *port)
}
-static void visor_unthrottle (struct usb_serial_port *port)
+static void visor_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
@@ -618,10 +615,13 @@ static void visor_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, result);
}
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_3_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
struct device *dev = &serial->dev->dev;
struct visor_connection_info *connection_info;
@@ -633,7 +633,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
dbg("%s", __func__);
- transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
sizeof(*connection_info));
@@ -641,7 +641,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
}
/* send a get connection info request */
- retval = usb_control_msg (serial->dev,
+ retval = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_GET_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer,
@@ -653,29 +653,31 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
}
if (retval == sizeof(*connection_info)) {
- connection_info = (struct visor_connection_info *)transfer_buffer;
+ connection_info = (struct visor_connection_info *)
+ transfer_buffer;
num_ports = le16_to_cpu(connection_info->num_ports);
for (i = 0; i < num_ports; ++i) {
- switch (connection_info->connections[i].port_function_id) {
- case VISOR_FUNCTION_GENERIC:
- string = "Generic";
- break;
- case VISOR_FUNCTION_DEBUGGER:
- string = "Debugger";
- break;
- case VISOR_FUNCTION_HOTSYNC:
- string = "HotSync";
- break;
- case VISOR_FUNCTION_CONSOLE:
- string = "Console";
- break;
- case VISOR_FUNCTION_REMOTE_FILE_SYS:
- string = "Remote File System";
- break;
- default:
- string = "unknown";
- break;
+ switch (
+ connection_info->connections[i].port_function_id) {
+ case VISOR_FUNCTION_GENERIC:
+ string = "Generic";
+ break;
+ case VISOR_FUNCTION_DEBUGGER:
+ string = "Debugger";
+ break;
+ case VISOR_FUNCTION_HOTSYNC:
+ string = "HotSync";
+ break;
+ case VISOR_FUNCTION_CONSOLE:
+ string = "Console";
+ break;
+ case VISOR_FUNCTION_REMOTE_FILE_SYS:
+ string = "Remote File System";
+ break;
+ default:
+ string = "unknown";
+ break;
}
dev_info(dev, "%s: port %d, is for %s use\n",
serial->type->description,
@@ -686,11 +688,11 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
* Handle devices that report invalid stuff here.
*/
if (num_ports == 0 || num_ports > 2) {
- dev_warn (dev, "%s: No valid connect info available\n",
+ dev_warn(dev, "%s: No valid connect info available\n",
serial->type->description);
num_ports = 2;
}
-
+
dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
num_ports);
@@ -700,8 +702,9 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
*/
usb_set_serial_data(serial, (void *)(long)num_ports);
- /* ask for the number of bytes available, but ignore the response as it is broken */
- retval = usb_control_msg (serial->dev,
+ /* ask for the number of bytes available, but ignore the
+ response as it is broken */
+ retval = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_REQUEST_BYTES_AVAILABLE,
0xc2, 0x0000, 0x0005, transfer_buffer,
@@ -712,12 +715,13 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
retval = 0;
exit:
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return retval;
}
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_4_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
struct device *dev = &serial->dev->dev;
struct palm_ext_connection_info *connection_info;
@@ -726,18 +730,18 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
dbg("%s", __func__);
- transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+ transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
if (!transfer_buffer) {
dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
sizeof(*connection_info));
return -ENOMEM;
}
- retval = usb_control_msg (serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
+ retval = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
PALM_GET_EXT_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer,
- sizeof (*connection_info), 300);
+ sizeof(*connection_info), 300);
if (retval < 0)
dev_err(dev, "%s - error %d getting connection info\n",
__func__, retval);
@@ -745,15 +749,17 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
usb_serial_debug_data(debug, &serial->dev->dev, __func__,
retval, transfer_buffer);
- kfree (transfer_buffer);
+ kfree(transfer_buffer);
return 0;
}
-static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int visor_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
int retval = 0;
- int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
+ int (*startup)(struct usb_serial *serial,
+ const struct usb_device_id *id);
dbg("%s", __func__);
@@ -771,7 +777,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id *i
return retval;
}
-static int visor_calc_num_ports (struct usb_serial *serial)
+static int visor_calc_num_ports(struct usb_serial *serial)
{
int num_ports = (int)(long)(usb_get_serial_data(serial));
@@ -788,7 +794,7 @@ static int generic_startup(struct usb_serial *serial)
int i;
for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc (sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
while (i-- != 0) {
priv = usb_get_serial_port_data(ports[i]);
@@ -803,7 +809,7 @@ static int generic_startup(struct usb_serial *serial)
return 0;
}
-static int clie_3_5_startup (struct usb_serial *serial)
+static int clie_3_5_startup(struct usb_serial *serial)
{
struct device *dev = &serial->dev->dev;
int result;
@@ -816,62 +822,72 @@ static int clie_3_5_startup (struct usb_serial *serial)
*/
/* get the config number */
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
0, 0, &data, 1, 3000);
if (result < 0) {
- dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
+ dev_err(dev, "%s: get config number failed: %d\n",
+ __func__, result);
return result;
}
if (result != 1) {
- dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
+ dev_err(dev, "%s: get config number bad return length: %d\n",
+ __func__, result);
return -EIO;
}
/* get the interface number */
- result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- USB_REQ_GET_INTERFACE,
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQ_GET_INTERFACE,
USB_DIR_IN | USB_RECIP_INTERFACE,
0, 0, &data, 1, 3000);
if (result < 0) {
- dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
+ dev_err(dev, "%s: get interface number failed: %d\n",
+ __func__, result);
return result;
}
if (result != 1) {
- dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
+ dev_err(dev,
+ "%s: get interface number bad return length: %d\n",
+ __func__, result);
return -EIO;
}
return generic_startup(serial);
}
-
-static int treo_attach (struct usb_serial *serial)
+
+static int treo_attach(struct usb_serial *serial)
{
struct usb_serial_port *swap_port;
/* Only do this endpoint hack for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices. */
- if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) ||
- (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) ||
- (serial->num_interrupt_in == 0))
+ if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
+ == HANDSPRING_VENDOR_ID) ||
+ (le16_to_cpu(serial->dev->descriptor.idVendor)
+ == KYOCERA_VENDOR_ID)) ||
+ (serial->num_interrupt_in == 0))
goto generic_startup;
dbg("%s", __func__);
/*
- * It appears that Treos and Kyoceras want to use the
- * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
- * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
- * Note that swapping the bulk out endpoints would break lots of
+ * It appears that Treos and Kyoceras want to use the
+ * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
+ * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
+ * Note that swapping the bulk out endpoints would break lots of
* apps that want to communicate on the second port.
*/
#define COPY_PORT(dest, src) \
- dest->read_urb = src->read_urb; \
- dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \
- dest->bulk_in_buffer = src->bulk_in_buffer; \
- dest->interrupt_in_urb = src->interrupt_in_urb; \
- dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \
- dest->interrupt_in_buffer = src->interrupt_in_buffer;
+ do { \
+ dest->read_urb = src->read_urb; \
+ dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
+ dest->bulk_in_buffer = src->bulk_in_buffer; \
+ dest->interrupt_in_urb = src->interrupt_in_urb; \
+ dest->interrupt_in_endpointAddress = \
+ src->interrupt_in_endpointAddress;\
+ dest->interrupt_in_buffer = src->interrupt_in_buffer; \
+ } while (0);
swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
if (!swap_port)
@@ -885,28 +901,30 @@ generic_startup:
return generic_startup(serial);
}
-static int clie_5_attach (struct usb_serial *serial)
+static int clie_5_attach(struct usb_serial *serial)
{
dbg("%s", __func__);
- /* TH55 registers 2 ports.
- Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0
- Communication out to the UX50/TH55 uses bulk_out_endpointAddress from port 1
-
+ /* TH55 registers 2 ports.
+ Communication in from the UX50/TH55 uses bulk_in_endpointAddress
+ from port 0. Communication out to the UX50/TH55 uses
+ bulk_out_endpointAddress from port 1
+
Lets do a quick and dirty mapping
*/
-
+
/* some sanity check */
if (serial->num_ports < 2)
return -1;
-
+
/* port 0 now uses the modified endpoint Address */
- serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress;
+ serial->port[0]->bulk_out_endpointAddress =
+ serial->port[1]->bulk_out_endpointAddress;
return generic_startup(serial);
}
-static void visor_shutdown (struct usb_serial *serial)
+static void visor_shutdown(struct usb_serial *serial)
{
struct visor_private *priv;
int i;
@@ -922,37 +940,35 @@ static void visor_shutdown (struct usb_serial *serial)
}
}
-static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
- dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
- return -ENOIOCTLCMD;
-}
-
-static int __init visor_init (void)
+static int __init visor_init(void)
{
int i, retval;
/* Only if parameters were passed to us */
- if ((vendor>0) && (product>0)) {
- struct usb_device_id usb_dev_temp[]=
- {{USB_DEVICE(vendor, product),
- .driver_info = (kernel_ulong_t)&palm_os_4_probe }};
+ if (vendor > 0 && product > 0) {
+ struct usb_device_id usb_dev_temp[] = {
+ {
+ USB_DEVICE(vendor, product),
+ .driver_info =
+ (kernel_ulong_t) &palm_os_4_probe
+ }
+ };
/* Find the last entry in id_table */
- for (i=0; ; i++) {
- if (id_table[i].idVendor==0) {
+ for (i = 0;; i++) {
+ if (id_table[i].idVendor == 0) {
id_table[i] = usb_dev_temp[0];
break;
}
}
/* Find the last entry in id_table_combined */
- for (i=0; ; i++) {
- if (id_table_combined[i].idVendor==0) {
+ for (i = 0;; i++) {
+ if (id_table_combined[i].idVendor == 0) {
id_table_combined[i] = usb_dev_temp[0];
break;
}
}
- info("Untested USB device specified at time of module insertion");
+ info(
+ "Untested USB device specified at time of module insertion");
info("Warning: This is not guaranteed to work");
info("Using a newer kernel is preferred to this method");
info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x",
@@ -968,7 +984,7 @@ static int __init visor_init (void)
if (retval)
goto failed_clie_5_register;
retval = usb_register(&visor_driver);
- if (retval)
+ if (retval)
goto failed_usb_register;
info(DRIVER_DESC);
@@ -986,18 +1002,18 @@ failed_handspring_register:
static void __exit visor_exit (void)
{
- usb_deregister (&visor_driver);
- usb_serial_deregister (&handspring_device);
- usb_serial_deregister (&clie_3_5_device);
- usb_serial_deregister (&clie_5_device);
+ usb_deregister(&visor_driver);
+ usb_serial_deregister(&handspring_device);
+ usb_serial_deregister(&clie_3_5_device);
+ usb_serial_deregister(&clie_5_device);
}
module_init(visor_init);
module_exit(visor_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 665aa77a917..3a9d14384a4 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -12,29 +12,31 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
* (10/09/2002) Stuart MacDonald (stuartm@connecttech.com)
* Upgrade to full working driver
*
* (05/30/2001) gkh
- * switched from using spinlock to a semaphore, which fixes lots of problems.
+ * switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
*
* (04/08/2001) gb
* Identify version on module load.
- *
+ *
* 2001_Mar_19 gkh
- * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
+ * Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
* than once, and the got the proper usb_device_id table entries so
* the driver works again.
*
* (11/01/2000) Adam J. Richter
* usb_device_id table support
- *
+ *
* (10/05/2000) gkh
* Fixed bug with urb->dev not being set properly, now that the usb
* core needs it.
- *
+ *
* (10/03/2000) smd
* firmware is improved to guard against crap sent to device
* firmware now replies CMD_FAILURE on bad things
@@ -52,9 +54,9 @@
* Fixed bug with port->minor that was found by Al Borchers
*
* (07/04/2000) gkh
- * Added support for port settings. Baud rate can now be changed. Line signals
- * are not transferred to and from the tty layer yet, but things seem to be
- * working well now.
+ * Added support for port settings. Baud rate can now be changed. Line
+ * signals are not transferred to and from the tty layer yet, but things
+ * seem to be working well now.
*
* (05/04/2000) gkh
* First cut at open and close commands. Data can flow through the ports at
@@ -62,7 +64,7 @@
*
* (03/26/2000) gkh
* Split driver up into device specific pieces.
- *
+ *
*/
#include <linux/kernel.h>
@@ -75,7 +77,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/termbits.h>
#include <linux/usb.h>
#include <linux/serial_reg.h>
@@ -125,7 +127,7 @@ static struct usb_device_id id_table_combined [] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
static struct usb_driver whiteheat_driver = {
.name = "whiteheat",
@@ -136,26 +138,34 @@ static struct usb_driver whiteheat_driver = {
};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
-static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id);
-static int whiteheat_firmware_attach (struct usb_serial *serial);
+static int whiteheat_firmware_download(struct usb_serial *serial,
+ const struct usb_device_id *id);
+static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
-static int whiteheat_attach (struct usb_serial *serial);
-static void whiteheat_shutdown (struct usb_serial *serial);
-static int whiteheat_open (struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
-static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int whiteheat_write_room (struct usb_serial_port *port);
-static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old);
-static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
-static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
-static int whiteheat_chars_in_buffer (struct usb_serial_port *port);
-static void whiteheat_throttle (struct usb_serial_port *port);
-static void whiteheat_unthrottle (struct usb_serial_port *port);
-static void whiteheat_read_callback (struct urb *urb);
-static void whiteheat_write_callback (struct urb *urb);
+static int whiteheat_attach(struct usb_serial *serial);
+static void whiteheat_shutdown(struct usb_serial *serial);
+static int whiteheat_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp);
+static int whiteheat_write(struct tty_struct *tty,
+ struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int whiteheat_write_room(struct tty_struct *tty);
+static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void whiteheat_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old);
+static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file);
+static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
+static int whiteheat_chars_in_buffer(struct tty_struct *tty);
+static void whiteheat_throttle(struct tty_struct *tty);
+static void whiteheat_unthrottle(struct tty_struct *tty);
+static void whiteheat_read_callback(struct urb *urb);
+static void whiteheat_write_callback(struct urb *urb);
static struct usb_serial_driver whiteheat_fake_device = {
.driver = {
@@ -202,7 +212,9 @@ struct whiteheat_command_private {
struct mutex mutex;
__u8 port_running;
__u8 command_finished;
- wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */
+ wait_queue_head_t wait_command; /* for handling sleeping whilst
+ waiting for a command to
+ finish */
__u8 result_buffer[64];
};
@@ -239,14 +251,16 @@ static void command_port_write_callback(struct urb *urb);
static void command_port_read_callback(struct urb *urb);
static int start_port_read(struct usb_serial_port *port);
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+ struct list_head *head);
static struct list_head *list_first(struct list_head *head);
static void rx_data_softint(struct work_struct *work);
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+ __u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
static int firm_close(struct usb_serial_port *port);
-static int firm_setup_port(struct usb_serial_port *port);
+static int firm_setup_port(struct tty_struct *tty);
static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
@@ -278,7 +292,8 @@ static int firm_report_tx_done(struct usb_serial_port *port);
- device renumerated itself and comes up as new device id with all
firmware download completed.
*/
-static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id)
+static int whiteheat_firmware_download(struct usb_serial *serial,
+ const struct usb_device_id *id)
{
int response, ret = -ENOENT;
const struct firmware *loader_fw = NULL, *firmware_fw = NULL;
@@ -313,7 +328,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
record = ihex_next_binrec(record);
}
- response = ezusb_set_reset (serial, 0);
+ response = ezusb_set_reset(serial, 0);
record = (const struct ihex_binrec *)firmware_fw->data;
while (record && be32_to_cpu(record->addr) < 0x1b40)
@@ -330,8 +345,8 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
}
++record;
}
-
- response = ezusb_set_reset (serial, 1);
+
+ response = ezusb_set_reset(serial, 1);
record = (const struct ihex_binrec *)firmware_fw->data;
while (record && be32_to_cpu(record->addr) < 0x1b40) {
@@ -355,7 +370,7 @@ static int whiteheat_firmware_download (struct usb_serial *serial, const struct
}
-static int whiteheat_firmware_attach (struct usb_serial *serial)
+static int whiteheat_firmware_attach(struct usb_serial *serial)
{
/* We want this device to fail to have a driver assigned to it */
return 1;
@@ -365,7 +380,7 @@ static int whiteheat_firmware_attach (struct usb_serial *serial)
/*****************************************************************************
* Connect Tech's White Heat serial driver functions
*****************************************************************************/
-static int whiteheat_attach (struct usb_serial *serial)
+static int whiteheat_attach(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
@@ -386,43 +401,52 @@ static int whiteheat_attach (struct usb_serial *serial)
command_port = serial->port[COMMAND_PORT];
- pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
+ pipe = usb_sndbulkpipe(serial->dev,
+ command_port->bulk_out_endpointAddress);
command = kmalloc(2, GFP_KERNEL);
if (!command)
goto no_command_buffer;
command[0] = WHITEHEAT_GET_HW_INFO;
command[1] = 0;
-
+
result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL);
if (!result)
goto no_result_buffer;
/*
* When the module is reloaded the firmware is still there and
* the endpoints are still in the usb core unchanged. This is the
- * unlinking bug in disguise. Same for the call below.
- */
+ * unlinking bug in disguise. Same for the call below.
+ */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
+ ret = usb_bulk_msg(serial->dev, pipe, command, 2,
+ &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't send command [%d]", serial->type->description, ret);
+ err("%s: Couldn't send command [%d]",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != 2) {
- err("%s: Send command incomplete [%d]", serial->type->description, alen);
+ err("%s: Send command incomplete [%d]",
+ serial->type->description, alen);
goto no_firmware;
}
- pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
+ pipe = usb_rcvbulkpipe(serial->dev,
+ command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
+ ret = usb_bulk_msg(serial->dev, pipe, result,
+ sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
- err("%s: Couldn't get results [%d]", serial->type->description, ret);
+ err("%s: Couldn't get results [%d]",
+ serial->type->description, ret);
goto no_firmware;
} else if (alen != sizeof(*hw_info) + 1) {
- err("%s: Get results incomplete [%d]", serial->type->description, alen);
+ err("%s: Get results incomplete [%d]",
+ serial->type->description, alen);
goto no_firmware;
} else if (result[0] != command[0]) {
- err("%s: Command failed [%d]", serial->type->description, result[0]);
+ err("%s: Command failed [%d]",
+ serial->type->description, result[0]);
goto no_firmware;
}
@@ -436,7 +460,8 @@ static int whiteheat_attach (struct usb_serial *serial)
info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->description);
+ err("%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_private;
}
@@ -506,9 +531,11 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_set_serial_port_data(port, info);
}
- command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private),
+ GFP_KERNEL);
if (command_info == NULL) {
- err("%s: Out of memory for port structures\n", serial->type->description);
+ err("%s: Out of memory for port structures\n",
+ serial->type->description);
goto no_command_private;
}
@@ -525,9 +552,12 @@ static int whiteheat_attach (struct usb_serial *serial)
no_firmware:
/* Firmware likely not running */
- err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
- err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
- err("%s: please contact support@connecttech.com\n", serial->type->description);
+ err("%s: Unable to retrieve firmware version, try replugging\n",
+ serial->type->description);
+ err("%s: If the firmware is not running (status led not blinking)\n",
+ serial->type->description);
+ err("%s: please contact support@connecttech.com\n",
+ serial->type->description);
kfree(result);
return -ENODEV;
@@ -570,7 +600,7 @@ no_command_buffer:
}
-static void whiteheat_shutdown (struct usb_serial *serial)
+static void whiteheat_shutdown(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct usb_serial_port *port;
@@ -585,7 +615,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
/* free up our private data for our command port */
command_port = serial->port[COMMAND_PORT];
- kfree (usb_get_serial_port_data(command_port));
+ kfree(usb_get_serial_port_data(command_port));
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -612,11 +642,10 @@ static void whiteheat_shutdown (struct usb_serial *serial)
return;
}
-
-static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+static int whiteheat_open(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
- struct ktermios old_term;
dbg("%s - port %d", __func__, port->number);
@@ -624,7 +653,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
if (retval)
goto exit;
- port->tty->low_latency = 1;
+ if (tty)
+ tty->low_latency = 1;
/* send an open port command */
retval = firm_open(port);
@@ -640,9 +670,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
goto exit;
}
- old_term.c_cflag = ~port->tty->termios->c_cflag;
- old_term.c_iflag = ~port->tty->termios->c_iflag;
- whiteheat_set_termios(port, &old_term);
+ if (tty)
+ firm_setup_port(tty);
/* Work around HCD bugs */
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
@@ -651,7 +680,8 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
/* Start reading from the device */
retval = start_port_read(port);
if (retval) {
- err("%s - failed submitting read urb, error %d", __func__, retval);
+ err("%s - failed submitting read urb, error %d",
+ __func__, retval);
firm_close(port);
stop_command_port(port->serial);
goto exit;
@@ -663,7 +693,8 @@ exit:
}
-static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+static void whiteheat_close(struct tty_struct *tty,
+ struct usb_serial_port *port, struct file *filp)
{
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
@@ -681,7 +712,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
}
mutex_unlock(&port->serial->disc_mutex);
- port->tty->closing = 1;
+ tty->closing = 1;
/*
* Not currently in use; tty_wait_until_sent() calls
@@ -689,12 +720,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
* acquisition. This should be fixed at some point. Greg's been
* notified.
if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
- tty_wait_until_sent(port->tty, CLOSING_DELAY);
+ tty_wait_until_sent(tty, CLOSING_DELAY);
}
*/
- tty_driver_flush_buffer(port->tty);
- tty_ldisc_flush(port->tty);
+ tty_driver_flush_buffer(tty);
+ tty_ldisc_flush(tty);
firm_report_tx_done(port);
@@ -728,11 +759,12 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
stop_command_port(port->serial);
- port->tty->closing = 0;
+ tty->closing = 0;
}
-static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int whiteheat_write(struct tty_struct *tty,
+ struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -763,16 +795,19 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
- bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
- memcpy (urb->transfer_buffer, buf + sent, bytes);
+ bytes = (count > port->bulk_out_size) ?
+ port->bulk_out_size : count;
+ memcpy(urb->transfer_buffer, buf + sent, bytes);
- usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, bytes, urb->transfer_buffer);
urb->dev = serial->dev;
urb->transfer_buffer_length = bytes;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed submitting write urb, error %d", __func__, result);
+ err("%s - failed submitting write urb, error %d",
+ __func__, result);
sent = result;
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->tx_urbs_free);
@@ -790,16 +825,16 @@ static int whiteheat_write(struct usb_serial_port *port, const unsigned char *bu
return sent;
}
-
-static int whiteheat_write_room(struct usb_serial_port *port)
+static int whiteheat_write_room(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
int room = 0;
unsigned long flags;
dbg("%s - port %d", __func__, port->number);
-
+
spin_lock_irqsave(&info->lock, flags);
list_for_each(tmp, &info->tx_urbs_free)
room++;
@@ -810,9 +845,9 @@ static int whiteheat_write_room(struct usb_serial_port *port)
return (room);
}
-
-static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
+static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
@@ -827,10 +862,10 @@ static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
return modem_signals;
}
-
-static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
+static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
dbg("%s - port %d", __func__, port->number);
@@ -851,65 +886,55 @@ static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
}
-static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
+ struct usb_serial_port *port = tty->driver_data;
struct serial_struct serstruct;
void __user *user_arg = (void __user *)arg;
dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
switch (cmd) {
- case TIOCGSERIAL:
- memset(&serstruct, 0, sizeof(serstruct));
- serstruct.type = PORT_16654;
- serstruct.line = port->serial->minor;
- serstruct.port = port->number;
- serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
- serstruct.xmit_fifo_size = port->bulk_out_size;
- serstruct.custom_divisor = 0;
- serstruct.baud_base = 460800;
- serstruct.close_delay = CLOSING_DELAY;
- serstruct.closing_wait = CLOSING_DELAY;
-
- if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
- return -EFAULT;
-
- break;
-
- case TIOCSSERIAL:
- if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
- return -EFAULT;
-
- /*
- * For now this is ignored. dip sets the ASYNC_[V]HI flags
- * but this isn't used by us at all. Maybe someone somewhere
- * will need the custom_divisor setting.
- */
-
- break;
-
- default:
- break;
+ case TIOCGSERIAL:
+ memset(&serstruct, 0, sizeof(serstruct));
+ serstruct.type = PORT_16654;
+ serstruct.line = port->serial->minor;
+ serstruct.port = port->number;
+ serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ serstruct.xmit_fifo_size = port->bulk_out_size;
+ serstruct.custom_divisor = 0;
+ serstruct.baud_base = 460800;
+ serstruct.close_delay = CLOSING_DELAY;
+ serstruct.closing_wait = CLOSING_DELAY;
+
+ if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
+ return -EFAULT;
+ break;
+ default:
+ break;
}
return -ENOIOCTLCMD;
}
-static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
{
- dbg("%s -port %d", __func__, port->number);
- firm_setup_port(port);
+ firm_setup_port(tty);
}
-
-static void whiteheat_break_ctl(struct usb_serial_port *port, int break_state) {
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct usb_serial_port *port = tty->driver_data;
firm_set_break(port, break_state);
}
-static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+static int whiteheat_chars_in_buffer(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
struct whiteheat_urb_wrap *wrap;
@@ -925,13 +950,14 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
}
spin_unlock_irqrestore(&info->lock, flags);
- dbg ("%s - returns %d", __func__, chars);
+ dbg("%s - returns %d", __func__, chars);
return chars;
}
-static void whiteheat_throttle (struct usb_serial_port *port)
+static void whiteheat_throttle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned long flags;
@@ -945,8 +971,9 @@ static void whiteheat_throttle (struct usb_serial_port *port)
}
-static void whiteheat_unthrottle (struct usb_serial_port *port)
+static void whiteheat_unthrottle(struct tty_struct *tty)
{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
@@ -993,7 +1020,7 @@ static void command_port_read_callback(struct urb *urb)
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
- dbg ("%s - command_info is NULL, exiting.", __func__);
+ dbg("%s - command_info is NULL, exiting.", __func__);
return;
}
if (status) {
@@ -1004,7 +1031,8 @@ static void command_port_read_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &command_port->dev,
+ __func__, urb->actual_length, data);
if (data[0] == WHITEHEAT_CMD_COMPLETE) {
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
@@ -1013,21 +1041,23 @@ static void command_port_read_callback(struct urb *urb)
command_info->command_finished = WHITEHEAT_CMD_FAILURE;
wake_up(&command_info->wait_command);
} else if (data[0] == WHITEHEAT_EVENT) {
- /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
+ /* These are unsolicited reports from the firmware, hence no
+ waiting command to wakeup */
dbg("%s - event received", __func__);
} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
- memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
+ memcpy(command_info->result_buffer, &data[1],
+ urb->actual_length - 1);
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
wake_up(&command_info->wait_command);
- } else {
+ } else
dbg("%s - bad reply from firmware", __func__);
- }
-
+
/* Continue trying to always read */
command_port->read_urb->dev = command_port->serial->dev;
result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
if (result)
- dbg("%s - failed resubmitting read urb, error %d", __func__, result);
+ dbg("%s - failed resubmitting read urb, error %d",
+ __func__, result);
}
@@ -1060,7 +1090,8 @@ static void whiteheat_read_callback(struct urb *urb)
return;
}
- usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
spin_lock(&info->lock);
list_add_tail(&wrap->list, &info->rx_urb_q);
@@ -1107,7 +1138,8 @@ static void whiteheat_write_callback(struct urb *urb)
/*****************************************************************************
* Connect Tech's White Heat firmware interface
*****************************************************************************/
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+ __u8 *data, __u8 datasize)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
@@ -1122,13 +1154,13 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
command_info = usb_get_serial_port_data(command_port);
mutex_lock(&command_info->mutex);
command_info->command_finished = false;
-
+
transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
transfer_buffer[0] = command;
- memcpy (&transfer_buffer[1], data, datasize);
+ memcpy(&transfer_buffer[1], data, datasize);
command_port->write_urb->transfer_buffer_length = datasize + 1;
command_port->write_urb->dev = port->serial->dev;
- retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
+ retval = usb_submit_urb(command_port->write_urb, GFP_NOIO);
if (retval) {
dbg("%s - submit urb failed", __func__);
goto exit;
@@ -1155,51 +1187,57 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *d
if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
dbg("%s - command completed.", __func__);
switch (command) {
- case WHITEHEAT_GET_DTR_RTS:
- info = usb_get_serial_port_data(port);
- memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info));
+ case WHITEHEAT_GET_DTR_RTS:
+ info = usb_get_serial_port_data(port);
+ memcpy(&info->mcr, command_info->result_buffer,
+ sizeof(struct whiteheat_dr_info));
break;
}
}
-
exit:
mutex_unlock(&command_info->mutex);
return retval;
}
-static int firm_open(struct usb_serial_port *port) {
+static int firm_open(struct usb_serial_port *port)
+{
struct whiteheat_simple open_command;
open_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
+ return firm_send_command(port, WHITEHEAT_OPEN,
+ (__u8 *)&open_command, sizeof(open_command));
}
-static int firm_close(struct usb_serial_port *port) {
+static int firm_close(struct usb_serial_port *port)
+{
struct whiteheat_simple close_command;
close_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
+ return firm_send_command(port, WHITEHEAT_CLOSE,
+ (__u8 *)&close_command, sizeof(close_command));
}
-static int firm_setup_port(struct usb_serial_port *port) {
+static int firm_setup_port(struct tty_struct *tty)
+{
+ struct usb_serial_port *port = tty->driver_data;
struct whiteheat_port_settings port_settings;
- unsigned int cflag = port->tty->termios->c_cflag;
+ unsigned int cflag = tty->termios->c_cflag;
port_settings.port = port->number + 1;
/* get the byte size */
switch (cflag & CSIZE) {
- case CS5: port_settings.bits = 5; break;
- case CS6: port_settings.bits = 6; break;
- case CS7: port_settings.bits = 7; break;
- default:
- case CS8: port_settings.bits = 8; break;
+ case CS5: port_settings.bits = 5; break;
+ case CS6: port_settings.bits = 6; break;
+ case CS7: port_settings.bits = 7; break;
+ default:
+ case CS8: port_settings.bits = 8; break;
}
dbg("%s - data bits = %d", __func__, port_settings.bits);
-
+
/* determine the parity */
if (cflag & PARENB)
if (cflag & CMSPAR)
@@ -1225,7 +1263,8 @@ static int firm_setup_port(struct usb_serial_port *port) {
/* figure out the flow control settings */
if (cflag & CRTSCTS)
- port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
+ port_settings.hflow = (WHITEHEAT_HFLOW_CTS |
+ WHITEHEAT_HFLOW_RTS);
else
port_settings.hflow = WHITEHEAT_HFLOW_NONE;
dbg("%s - hardware flow control = %s %s %s %s", __func__,
@@ -1233,81 +1272,95 @@ static int firm_setup_port(struct usb_serial_port *port) {
(port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
(port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : "");
-
+
/* determine software flow control */
- if (I_IXOFF(port->tty))
+ if (I_IXOFF(tty))
port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
else
port_settings.sflow = WHITEHEAT_SFLOW_NONE;
dbg("%s - software flow control = %c", __func__, port_settings.sflow);
-
- port_settings.xon = START_CHAR(port->tty);
- port_settings.xoff = STOP_CHAR(port->tty);
- dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
+
+ port_settings.xon = START_CHAR(tty);
+ port_settings.xoff = STOP_CHAR(tty);
+ dbg("%s - XON = %2x, XOFF = %2x",
+ __func__, port_settings.xon, port_settings.xoff);
/* get the baud rate wanted */
- port_settings.baud = tty_get_baud_rate(port->tty);
+ port_settings.baud = tty_get_baud_rate(tty);
dbg("%s - baud rate = %d", __func__, port_settings.baud);
/* fixme: should set validated settings */
- tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+ tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
/* handle any settings that aren't specified in the tty structure */
port_settings.lloop = 0;
-
+
/* now send the message to the device */
- return firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings));
+ return firm_send_command(port, WHITEHEAT_SETUP_PORT,
+ (__u8 *)&port_settings, sizeof(port_settings));
}
-static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_rts(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb rts_command;
rts_command.port = port->number - port->serial->minor + 1;
rts_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command));
+ return firm_send_command(port, WHITEHEAT_SET_RTS,
+ (__u8 *)&rts_command, sizeof(rts_command));
}
-static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb dtr_command;
dtr_command.port = port->number - port->serial->minor + 1;
dtr_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&dtr_command, sizeof(dtr_command));
+ return firm_send_command(port, WHITEHEAT_SET_DTR,
+ (__u8 *)&dtr_command, sizeof(dtr_command));
}
-static int firm_set_break(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_break(struct usb_serial_port *port, __u8 onoff)
+{
struct whiteheat_set_rdb break_command;
break_command.port = port->number - port->serial->minor + 1;
break_command.state = onoff;
- return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&break_command, sizeof(break_command));
+ return firm_send_command(port, WHITEHEAT_SET_BREAK,
+ (__u8 *)&break_command, sizeof(break_command));
}
-static int firm_purge(struct usb_serial_port *port, __u8 rxtx) {
+static int firm_purge(struct usb_serial_port *port, __u8 rxtx)
+{
struct whiteheat_purge purge_command;
purge_command.port = port->number - port->serial->minor + 1;
purge_command.what = rxtx;
- return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command));
+ return firm_send_command(port, WHITEHEAT_PURGE,
+ (__u8 *)&purge_command, sizeof(purge_command));
}
-static int firm_get_dtr_rts(struct usb_serial_port *port) {
+static int firm_get_dtr_rts(struct usb_serial_port *port)
+{
struct whiteheat_simple get_dr_command;
get_dr_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command));
+ return firm_send_command(port, WHITEHEAT_GET_DTR_RTS,
+ (__u8 *)&get_dr_command, sizeof(get_dr_command));
}
-static int firm_report_tx_done(struct usb_serial_port *port) {
+static int firm_report_tx_done(struct usb_serial_port *port)
+{
struct whiteheat_simple close_command;
close_command.port = port->number - port->serial->minor + 1;
- return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command));
+ return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE,
+ (__u8 *)&close_command, sizeof(close_command));
}
@@ -1319,7 +1372,7 @@ static int start_command_port(struct usb_serial *serial)
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
int retval = 0;
-
+
command_port = serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
mutex_lock(&command_info->mutex);
@@ -1330,7 +1383,8 @@ static int start_command_port(struct usb_serial *serial)
command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) {
- err("%s - failed submitting read urb, error %d", __func__, retval);
+ err("%s - failed submitting read urb, error %d",
+ __func__, retval);
goto exit;
}
}
@@ -1400,7 +1454,8 @@ static int start_port_read(struct usb_serial_port *port)
}
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head)
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+ struct list_head *head)
{
struct whiteheat_urb_wrap *wrap;
struct list_head *tmp;
@@ -1426,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work)
struct whiteheat_private *info =
container_of(work, struct whiteheat_private, rx_work);
struct usb_serial_port *port = info->port;
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = port->port.tty;
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
unsigned long flags;
@@ -1449,7 +1504,8 @@ static void rx_data_softint(struct work_struct *work)
urb = wrap->urb;
if (tty && urb->actual_length) {
- int len = tty_buffer_request_room(tty, urb->actual_length);
+ int len = tty_buffer_request_room(tty,
+ urb->actual_length);
/* This stuff can go away now I suspect */
if (unlikely(len < urb->actual_length)) {
spin_lock_irqsave(&info->lock, flags);
@@ -1466,7 +1522,8 @@ static void rx_data_softint(struct work_struct *work)
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- err("%s - failed resubmitting read urb, error %d", __func__, result);
+ err("%s - failed resubmitting read urb, error %d",
+ __func__, result);
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urbs_free);
continue;
@@ -1485,7 +1542,7 @@ static void rx_data_softint(struct work_struct *work)
/*****************************************************************************
* Connect Tech's White Heat module functions
*****************************************************************************/
-static int __init whiteheat_init (void)
+static int __init whiteheat_init(void)
{
int retval;
retval = usb_serial_register(&whiteheat_fake_device);
@@ -1508,19 +1565,19 @@ failed_fake_register:
}
-static void __exit whiteheat_exit (void)
+static void __exit whiteheat_exit(void)
{
- usb_deregister (&whiteheat_driver);
- usb_serial_deregister (&whiteheat_fake_device);
- usb_serial_deregister (&whiteheat_device);
+ usb_deregister(&whiteheat_driver);
+ usb_serial_deregister(&whiteheat_fake_device);
+ usb_serial_deregister(&whiteheat_device);
}
module_init(whiteheat_init);
module_exit(whiteheat_exit);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("whiteheat.fw");
diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h
index f1607970566..38065df4d2d 100644
--- a/drivers/usb/serial/whiteheat.h
+++ b/drivers/usb/serial/whiteheat.h
@@ -2,7 +2,7 @@
* USB ConnectTech WhiteHEAT driver
*
* Copyright (C) 2002
- * Connect Tech Inc.
+ * Connect Tech Inc.
*
* Copyright (C) 1999, 2000
* Greg Kroah-Hartman (greg@kroah.com)
@@ -12,7 +12,8 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
*
*/
@@ -30,13 +31,16 @@
#define WHITEHEAT_DUMP 7 /* dump memory */
#define WHITEHEAT_STATUS 8 /* get status */
#define WHITEHEAT_PURGE 9 /* clear the UART fifos */
-#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS for a port */
-#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and hardware ID */
+#define WHITEHEAT_GET_DTR_RTS 10 /* get the state of DTR and RTS
+ for a port */
+#define WHITEHEAT_GET_HW_INFO 11 /* get EEPROM info and
+ hardware ID */
#define WHITEHEAT_REPORT_TX_DONE 12 /* get the next TX done */
#define WHITEHEAT_EVENT 13 /* unsolicited status events */
-#define WHITEHEAT_ECHO 14 /* send data to the indicated IN endpoint */
-#define WHITEHEAT_DO_TEST 15 /* perform the specified test */
-#define WHITEHEAT_CMD_COMPLETE 16 /* reply for certain commands */
+#define WHITEHEAT_ECHO 14 /* send data to the indicated
+ IN endpoint */
+#define WHITEHEAT_DO_TEST 15 /* perform specified test */
+#define WHITEHEAT_CMD_COMPLETE 16 /* reply for some commands */
#define WHITEHEAT_CMD_FAILURE 17 /* reply for failed commands */
@@ -67,20 +71,28 @@ struct whiteheat_simple {
#define WHITEHEAT_PAR_MARK '1' /* mark (force 1) parity */
#define WHITEHEAT_SFLOW_NONE 'n' /* no software flow control */
-#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX fills/empties */
-#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will stop/start TX */
+#define WHITEHEAT_SFLOW_RX 'r' /* XOFF/ON is sent when RX
+ fills/empties */
+#define WHITEHEAT_SFLOW_TX 't' /* when received XOFF/ON will
+ stop/start TX */
#define WHITEHEAT_SFLOW_RXTX 'b' /* both SFLOW_RX and SFLOW_TX */
#define WHITEHEAT_HFLOW_NONE 0x00 /* no hardware flow control */
-#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit, off otherwise */
-#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX fills/empties */
-#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX fills/empties */
+#define WHITEHEAT_HFLOW_RTS_TOGGLE 0x01 /* RTS is on during transmit,
+ off otherwise */
+#define WHITEHEAT_HFLOW_DTR 0x02 /* DTR is off/on when RX
+ fills/empties */
+#define WHITEHEAT_HFLOW_CTS 0x08 /* when received CTS off/on
+ will stop/start TX */
+#define WHITEHEAT_HFLOW_DSR 0x10 /* when received DSR off/on
+ will stop/start TX */
+#define WHITEHEAT_HFLOW_RTS 0x80 /* RTS is off/on when RX
+ fills/empties */
struct whiteheat_port_settings {
__u8 port; /* port number (1 to N) */
- __u32 baud; /* any value 7 - 460800, firmware calculates best fit; arrives little endian */
+ __u32 baud; /* any value 7 - 460800, firmware calculates
+ best fit; arrives little endian */
__u8 bits; /* 5, 6, 7, or 8 */
__u8 stop; /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
__u8 parity; /* see WHITEHEAT_PAR_* above */
@@ -167,12 +179,14 @@ struct whiteheat_echo {
*/
#define WHITEHEAT_TEST_UART_RW 0x01 /* read/write uart registers */
#define WHITEHEAT_TEST_UART_INTR 0x02 /* uart interrupt */
-#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for PORT_CONT/PORT_DISCONT */
+#define WHITEHEAT_TEST_SETUP_CONT 0x03 /* setup for
+ PORT_CONT/PORT_DISCONT */
#define WHITEHEAT_TEST_PORT_CONT 0x04 /* port connect */
#define WHITEHEAT_TEST_PORT_DISCONT 0x05 /* port disconnect */
#define WHITEHEAT_TEST_UART_CLK_START 0x06 /* uart clock test start */
#define WHITEHEAT_TEST_UART_CLK_STOP 0x07 /* uart clock test stop */
-#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a loopback cable/connector */
+#define WHITEHEAT_TEST_MODEM_FT 0x08 /* modem signals, requires a
+ loopback cable/connector */
#define WHITEHEAT_TEST_ERASE_EEPROM 0x09 /* erase eeprom */
#define WHITEHEAT_TEST_READ_EEPROM 0x0a /* read eeprom */
#define WHITEHEAT_TEST_PROGRAM_EEPROM 0x0b /* program eeprom */
@@ -198,19 +212,27 @@ struct whiteheat_test {
#define WHITEHEAT_EVENT_CONNECT 0x08 /* connect field is valid */
#define WHITEHEAT_FLOW_NONE 0x00 /* no flow control active */
-#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS (waiting for CTS to go on) */
-#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped by RTS */
-#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF received (waiting for XON) */
-#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF transmitted */
+#define WHITEHEAT_FLOW_HARD_OUT 0x01 /* TX is stopped by CTS
+ (waiting for CTS to go on) */
+#define WHITEHEAT_FLOW_HARD_IN 0x02 /* remote TX is stopped
+ by RTS */
+#define WHITEHEAT_FLOW_SOFT_OUT 0x04 /* TX is stopped by XOFF
+ received (waiting for XON) */
+#define WHITEHEAT_FLOW_SOFT_IN 0x08 /* remote TX is stopped by XOFF
+ transmitted */
#define WHITEHEAT_FLOW_TX_DONE 0x80 /* TX has completed */
struct whiteheat_status_info {
__u8 port; /* port number (1 to N) */
- __u8 event; /* indicates what the current event is, see WHITEHEAT_EVENT_* above */
- __u8 modem; /* modem signal status (copy of uart's MSR register) */
+ __u8 event; /* indicates what the current event is,
+ see WHITEHEAT_EVENT_* above */
+ __u8 modem; /* modem signal status (copy of uart's
+ MSR register) */
__u8 error; /* line status (copy of uart's LSR register) */
- __u8 flow; /* flow control state, see WHITEHEAT_FLOW_* above */
- __u8 connect; /* 0 means not connected, non-zero means connected */
+ __u8 flow; /* flow control state, see WHITEHEAT_FLOW_*
+ above */
+ __u8 connect; /* 0 means not connected, non-zero means
+ connected */
};
@@ -256,7 +278,8 @@ struct whiteheat_hw_info {
struct whiteheat_event_info {
__u8 port; /* port number (1 to N) */
__u8 event; /* see whiteheat_status_info.event */
- __u8 info; /* see whiteheat_status_info.modem, .error, .flow, .connect */
+ __u8 info; /* see whiteheat_status_info.modem, .error,
+ .flow, .connect */
};
@@ -269,7 +292,8 @@ struct whiteheat_event_info {
struct whiteheat_test_info {
__u8 port; /* port number (1 to N) */
- __u8 test; /* indicates which test this is a response for, see WHITEHEAT_DO_TEST above */
+ __u8 test; /* indicates which test this is a response for,
+ see WHITEHEAT_DO_TEST above */
__u8 status; /* see WHITEHEAT_TEST_* above */
__u8 results[32]; /* test-dependent results */
};
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 579e9f52053..17f1ae23291 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -1,7 +1,5 @@
/* Driver for Datafab USB Compact Flash reader
*
- * $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
- *
* datafab driver v0.1:
*
* First release
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 01e430654a1..a2b5526c9fa 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Source Code File
*
- * $Id: debug.c,v 1.9 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index 77e244a8c37..dbb985d5242 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Debugging Functions Header File
*
- * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index 9a410b5a6e5..939923471af 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -1,7 +1,5 @@
/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
*
- * $Id: dpcm.c,v 1.4 2001/06/11 02:54:25 mdharm Exp $
- *
* DPCM driver v0.1:
*
* First release
diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
index 81b464cfcc1..e7b7b0f120d 100644
--- a/drivers/usb/storage/dpcm.h
+++ b/drivers/usb/storage/dpcm.h
@@ -1,7 +1,5 @@
/* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
*
- * $Id: dpcm.h,v 1.2 2000/08/25 00:13:51 mdharm Exp $
- *
* DPCM driver v0.1:
*
* First release
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index f5a4e8d6a3b..7a4d4567722 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -1,7 +1,5 @@
/* Driver for Freecom USB/IDE adaptor
*
- * $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $
- *
* Freecom v0.1:
*
* First release
diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
index 1b012d62d0a..20d0fe6ba0c 100644
--- a/drivers/usb/storage/freecom.h
+++ b/drivers/usb/storage/freecom.h
@@ -1,7 +1,5 @@
/* Driver for Freecom USB/IDE adaptor
*
- * $Id: freecom.h,v 1.4 2000/08/29 14:49:15 dlbrown Exp $
- *
* Freecom v0.1:
*
* First release
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 187dd1e0109..4995bb595ae 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -1,7 +1,5 @@
/* Special Initializers for certain USB Mass Storage devices
*
- * $Id: initializers.c,v 1.2 2000/09/06 22:35:57 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index ad3ffd4236c..529327fbb06 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -1,7 +1,5 @@
/* Header file for Special Initializers for certain USB Mass Storage devices
*
- * $Id: initializers.h,v 1.1 2000/08/29 23:07:02 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 3addcd8f827..383abf2516a 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1,7 +1,5 @@
/* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
*
- * $Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance:
* (C) 2001-2002 Björn Stenberg (bjorn@haxx.se)
*
@@ -586,7 +584,7 @@ static void isd200_invoke_transport( struct us_data *us,
/* if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
*/
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
US_DEBUGP("-- command was aborted\n");
goto Handle_Abort;
}
@@ -633,7 +631,7 @@ static void isd200_invoke_transport( struct us_data *us,
if (need_auto_sense) {
result = isd200_read_regs(us);
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
US_DEBUGP("-- auto-sense aborted\n");
goto Handle_Abort;
}
@@ -663,7 +661,7 @@ static void isd200_invoke_transport( struct us_data *us,
srb->result = DID_ABORT << 16;
/* permit the reset transfer to take place */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
+ clear_bit(US_FLIDX_ABORTING, &us->dflags);
/* Need reset here */
}
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 61097cbb158..df67f13c9e7 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -1,7 +1,5 @@
/* Driver for Lexar "Jumpshot" Compact Flash reader
*
- * $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
- *
* jumpshot driver v0.1:
*
* First release
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index b9b8ede61fb..3b3357e20ea 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -1,7 +1,5 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 8737a36891c..487056ffb51 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Protocol Functions Header File
*
- * $Id: protocol.h,v 1.4 2001/02/13 07:10:03 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 3fcde9f0fa5..09779f6a817 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
@@ -73,7 +71,6 @@ static const char* host_info(struct Scsi_Host *host)
static int slave_alloc (struct scsi_device *sdev)
{
struct us_data *us = host_to_us(sdev->host);
- struct usb_host_endpoint *bulk_in_ep;
/*
* Set the INQUIRY transfer length to 36. We don't use any of
@@ -82,16 +79,22 @@ static int slave_alloc (struct scsi_device *sdev)
*/
sdev->inquiry_len = 36;
- /* Scatter-gather buffers (all but the last) must have a length
- * divisible by the bulk maxpacket size. Otherwise a data packet
- * would end up being short, causing a premature end to the data
- * transfer. We'll use the maxpacket value of the bulk-IN pipe
- * to set the SCSI device queue's DMA alignment mask.
+ /* USB has unusual DMA-alignment requirements: Although the
+ * starting address of each scatter-gather element doesn't matter,
+ * the length of each element except the last must be divisible
+ * by the Bulk maxpacket value. There's currently no way to
+ * express this by block-layer constraints, so we'll cop out
+ * and simply require addresses to be aligned at 512-byte
+ * boundaries. This is okay since most block I/O involves
+ * hardware sectors that are multiples of 512 bytes in length,
+ * and since host controllers up through USB 2.0 have maxpacket
+ * values no larger than 512.
+ *
+ * But it doesn't suffice for Wireless USB, where Bulk maxpacket
+ * values can be as large as 2048. To make that work properly
+ * will require changes to the block layer.
*/
- bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
- blk_queue_update_dma_alignment(sdev->request_queue,
- le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
- /* wMaxPacketSize must be a power of 2 */
+ blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
/*
* The UFI spec treates the Peripheral Qualifier bits in an
@@ -116,10 +119,10 @@ static int slave_configure(struct scsi_device *sdev)
* while others have trouble with more than 64K. At this time we
* are limiting both to 32K (64 sectores).
*/
- if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
+ if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
unsigned int max_sectors = 64;
- if (us->flags & US_FL_MAX_SECTORS_MIN)
+ if (us->fflags & US_FL_MAX_SECTORS_MIN)
max_sectors = PAGE_CACHE_SIZE >> 9;
if (sdev->request_queue->max_sectors > max_sectors)
blk_queue_max_sectors(sdev->request_queue,
@@ -148,7 +151,7 @@ static int slave_configure(struct scsi_device *sdev)
* majority of devices work fine, but a few still can't
* handle it. The sd driver will simply assume those
* devices are write-enabled. */
- if (us->flags & US_FL_NO_WP_DETECT)
+ if (us->fflags & US_FL_NO_WP_DETECT)
sdev->skip_ms_page_3f = 1;
/* A number of devices have problems with MODE SENSE for
@@ -158,13 +161,13 @@ static int slave_configure(struct scsi_device *sdev)
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
- if (us->flags & US_FL_FIX_CAPACITY)
+ if (us->fflags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
/* A few disks have two indistinguishable version, one of
* which reports the correct capacity and the other does not.
* The sd driver has to guess which is the case. */
- if (us->flags & US_FL_CAPACITY_HEURISTICS)
+ if (us->fflags & US_FL_CAPACITY_HEURISTICS)
sdev->guess_capacity = 1;
/* Some devices report a SCSI revision level above 2 but are
@@ -213,7 +216,7 @@ static int slave_configure(struct scsi_device *sdev)
/* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
* REMOVAL command, so suppress those commands. */
- if (us->flags & US_FL_NOT_LOCKABLE)
+ if (us->fflags & US_FL_NOT_LOCKABLE)
sdev->lockable = 0;
/* this is to satisfy the compiler, tho I don't think the
@@ -238,7 +241,7 @@ static int queuecommand(struct scsi_cmnd *srb,
}
/* fail the command if we are disconnecting */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
US_DEBUGP("Fail command during disconnect\n");
srb->result = DID_NO_CONNECT << 16;
done(srb);
@@ -248,7 +251,7 @@ static int queuecommand(struct scsi_cmnd *srb,
/* enqueue the command and wake up the control thread */
srb->scsi_done = done;
us->srb = srb;
- up(&(us->sema));
+ complete(&us->cmnd_ready);
return 0;
}
@@ -280,9 +283,9 @@ static int command_abort(struct scsi_cmnd *srb)
* with the reset). Note that we must retain the host lock while
* calling usb_stor_stop_transport(); otherwise it might interfere
* with an auto-reset that begins as soon as we release the lock. */
- set_bit(US_FLIDX_TIMED_OUT, &us->flags);
- if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
- set_bit(US_FLIDX_ABORTING, &us->flags);
+ set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
+ if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) {
+ set_bit(US_FLIDX_ABORTING, &us->dflags);
usb_stor_stop_transport(us);
}
scsi_unlock(us_to_host(us));
@@ -329,7 +332,7 @@ void usb_stor_report_device_reset(struct us_data *us)
struct Scsi_Host *host = us_to_host(us);
scsi_report_device_reset(host, 0, 0);
- if (us->flags & US_FL_SCM_MULT_TARG) {
+ if (us->fflags & US_FL_SCM_MULT_TARG) {
for (i = 1; i < host->max_id; ++i)
scsi_report_device_reset(host, 0, i);
}
@@ -400,7 +403,7 @@ static int proc_info (struct Scsi_Host *host, char *buffer,
pos += sprintf(pos, " Quirks:");
#define US_FLAG(name, value) \
- if (us->flags & value) pos += sprintf(pos, " " #name);
+ if (us->fflags & value) pos += sprintf(pos, " " #name);
US_DO_ALL_FLAGS
#undef US_FLAG
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index 737e4fa6045..ffa1cca93d2 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* SCSI Connecting Glue Header File
*
- * $Id: scsiglue.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 8972b17da84..c5a54b872c2 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1,6 +1,5 @@
/* Driver for SanDisk SDDR-09 SmartMedia reader
*
- * $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2002 Andries Brouwer (aeb@cwi.nl)
* Developed with the assistance of:
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index c03089a9ec3..e50033ad7b1 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -1,8 +1,6 @@
/* Driver for SanDisk SDDR-09 SmartMedia reader
* Header File
*
- * $Id: sddr09.h,v 1.5 2000/08/25 00:13:51 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
* (c) 2002 Andries Brouwer (aeb@cwi.nl)
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 6d14327c921..0d8df757789 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -1,7 +1,5 @@
/* Driver for SanDisk SDDR-55 SmartMedia reader
*
- * $Id:$
- *
* SDDR55 driver v0.1:
*
* First release
diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
index d6bd32f6c9f..a815a0470c8 100644
--- a/drivers/usb/storage/sddr55.h
+++ b/drivers/usb/storage/sddr55.h
@@ -1,8 +1,6 @@
/* Driver for SanDisk SDDR-55 SmartMedia reader
* Header File
*
- * $Id:$
- *
* Current development and maintenance by:
* (c) 2002 Simon Munton
*
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 570c1250f6f..ae6d64810d2 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,7 +1,5 @@
/* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
*
- * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
* (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 3ddf143a1de..d8bfc43e904 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -1,8 +1,6 @@
/* Driver for SCM Microsystems USB-ATAPI cable
* Header File
*
- * $Id: shuttle_usbat.h,v 1.5 2000/09/17 14:44:52 groovyjava Exp $
- *
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
* (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 6610d2dd1e7..fcbbfdb7b2b 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1,7 +1,5 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.47 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
@@ -75,14 +73,14 @@
* by a separate code path.)
*
* The abort function (usb_storage_command_abort() in scsiglue.c) first
- * sets the machine state and the ABORTING bit in us->flags to prevent
+ * sets the machine state and the ABORTING bit in us->dflags to prevent
* new URBs from being submitted. It then calls usb_stor_stop_transport()
- * below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags
+ * below, which atomically tests-and-clears the URB_ACTIVE bit in us->dflags
* to see if the current_urb needs to be stopped. Likewise, the SG_ACTIVE
* bit is tested to see if the current_sg scatter-gather request needs to be
* stopped. The timeout callback routine does much the same thing.
*
- * When a disconnect occurs, the DISCONNECTING bit in us->flags is set to
+ * When a disconnect occurs, the DISCONNECTING bit in us->dflags is set to
* prevent new URBs from being submitted, and usb_stor_stop_transport() is
* called to stop any ongoing requests.
*
@@ -127,8 +125,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
long timeleft;
int status;
- /* don't submit URBs during abort/disconnect processing */
- if (us->flags & ABORTING_OR_DISCONNECTING)
+ /* don't submit URBs during abort processing */
+ if (test_bit(US_FLIDX_ABORTING, &us->dflags))
return -EIO;
/* set up data structures for the wakeup system */
@@ -159,13 +157,13 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
/* since the URB has been submitted successfully, it's now okay
* to cancel it */
- set_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+ set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
- /* did an abort/disconnect occur during the submission? */
- if (us->flags & ABORTING_OR_DISCONNECTING) {
+ /* did an abort occur during the submission? */
+ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
/* cancel the URB, if it hasn't been cancelled already */
- if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
+ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
@@ -175,7 +173,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
timeleft = wait_for_completion_interruptible_timeout(
&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
- clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+ clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
if (timeleft <= 0) {
US_DEBUGP("%s -- cancelling URB\n",
@@ -419,8 +417,8 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
{
int result;
- /* don't submit s-g requests during abort/disconnect processing */
- if (us->flags & ABORTING_OR_DISCONNECTING)
+ /* don't submit s-g requests during abort processing */
+ if (test_bit(US_FLIDX_ABORTING, &us->dflags))
return USB_STOR_XFER_ERROR;
/* initialize the scatter-gather request block */
@@ -435,13 +433,13 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* since the block has been initialized successfully, it's now
* okay to cancel it */
- set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
+ set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
- /* did an abort/disconnect occur during the submission? */
- if (us->flags & ABORTING_OR_DISCONNECTING) {
+ /* did an abort occur during the submission? */
+ if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
/* cancel the request, if it hasn't been cancelled already */
- if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
+ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
US_DEBUGP("-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
@@ -449,7 +447,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* wait for the completion of the transfer */
usb_sg_wait(&us->current_sg);
- clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
+ clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
result = us->current_sg.status;
if (act_len)
@@ -530,7 +528,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* if the command gets aborted by the higher layers, we need to
* short-circuit all other processing
*/
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
US_DEBUGP("-- command was aborted\n");
srb->result = DID_ABORT << 16;
goto Handle_Errors;
@@ -616,7 +614,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* let's clean up right away */
scsi_eh_restore_cmnd(srb, &ses);
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
US_DEBUGP("-- auto-sense aborted\n");
srb->result = DID_ABORT << 16;
goto Handle_Errors;
@@ -629,7 +627,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
* auto-sense is perfectly valid
*/
srb->result = DID_ERROR << 16;
- if (!(us->flags & US_FL_SCM_MULT_TARG))
+ if (!(us->fflags & US_FL_SCM_MULT_TARG))
goto Handle_Errors;
return;
}
@@ -679,8 +677,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* Set the RESETTING bit, and clear the ABORTING bit so that
* the reset may proceed. */
scsi_lock(us_to_host(us));
- set_bit(US_FLIDX_RESETTING, &us->flags);
- clear_bit(US_FLIDX_ABORTING, &us->flags);
+ set_bit(US_FLIDX_RESETTING, &us->dflags);
+ clear_bit(US_FLIDX_ABORTING, &us->dflags);
scsi_unlock(us_to_host(us));
/* We must release the device lock because the pre_reset routine
@@ -695,7 +693,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
scsi_unlock(us_to_host(us));
us->transport_reset(us);
}
- clear_bit(US_FLIDX_RESETTING, &us->flags);
+ clear_bit(US_FLIDX_RESETTING, &us->dflags);
}
/* Stop the current URB transfer */
@@ -707,13 +705,13 @@ void usb_stor_stop_transport(struct us_data *us)
* let's wake it up. The test_and_clear_bit() call
* guarantees that if a URB has just been submitted,
* it won't be cancelled more than once. */
- if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
+ if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
/* If we are waiting for a scatter-gather operation, cancel it. */
- if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
+ if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
US_DEBUGP("-- cancelling sg request\n");
usb_sg_cancel(&us->current_sg);
}
@@ -914,7 +912,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
/* Take care of BULK32 devices; set extra byte to 0 */
- if ( unlikely(us->flags & US_FL_BULK32)) {
+ if (unlikely(us->fflags & US_FL_BULK32)) {
cbwlen = 32;
us->iobuf[31] = 0;
}
@@ -925,7 +923,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
- if (us->flags & US_FL_SCM_MULT_TARG)
+ if (us->fflags & US_FL_SCM_MULT_TARG)
bcb->Lun |= srb->device->id << 4;
bcb->Length = srb->cmd_len;
@@ -951,7 +949,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* Some USB-IDE converter chips need a 100us delay between the
* command phase and the data phase. Some devices need a little
* more than that, probably because of clock rate inaccuracies. */
- if (unlikely(us->flags & US_FL_GO_SLOW))
+ if (unlikely(us->fflags & US_FL_GO_SLOW))
udelay(125);
if (transfer_length) {
@@ -1010,7 +1008,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status);
- if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) ||
+ if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
@@ -1035,7 +1033,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* try to compute the actual residue, based on how much data
* was really transferred and what the device tells us */
if (residue) {
- if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
+ if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
residue = min(residue, transfer_length);
scsi_set_resid(srb, max(scsi_get_resid(srb),
(int) residue));
@@ -1090,7 +1088,7 @@ static int usb_stor_reset_common(struct us_data *us,
int result;
int result2;
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
US_DEBUGP("No reset during disconnect\n");
return -EIO;
}
@@ -1103,12 +1101,12 @@ static int usb_stor_reset_common(struct us_data *us,
return result;
}
- /* Give the device some time to recover from the reset,
- * but don't delay disconnect processing. */
- wait_event_interruptible_timeout(us->delay_wait,
- test_bit(US_FLIDX_DISCONNECTING, &us->flags),
- HZ*6);
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ /* Give the device some time to recover from the reset,
+ * but don't delay disconnect processing. */
+ wait_event_interruptible_timeout(us->delay_wait,
+ test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
+ HZ*6);
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
US_DEBUGP("Reset interrupted by disconnect\n");
return -EIO;
}
@@ -1170,13 +1168,12 @@ int usb_stor_port_reset(struct us_data *us)
US_DEBUGP("unable to lock device for reset: %d\n", result);
else {
/* Were we disconnected while waiting for the lock? */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
result = -EIO;
US_DEBUGP("No reset during disconnect\n");
} else {
- result = usb_reset_composite_device(
- us->pusb_dev, us->pusb_intf);
- US_DEBUGP("usb_reset_composite_device returns %d\n",
+ result = usb_reset_device(us->pusb_dev);
+ US_DEBUGP("usb_reset_device returns %d\n",
result);
}
if (rc_lock)
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index ada7c2f43f8..e70b88182f0 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Transport Functions Header File
*
- * $Id: transport.h,v 1.18 2002/04/21 02:57:59 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 39a7c11795c..7ae69f55aa9 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Unusual Devices File
*
- * $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
@@ -1234,6 +1232,17 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_NOT_LOCKABLE),
+/* Andrew Lunn <andrew@lunn.ch>
+ * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
+ * on LUN 4.
+ * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera"
+*/
+UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200,
+ "PanDigital",
+ "Photo Frame",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NOT_LOCKABLE),
+
/* Submitted by Jan De Luyck <lkml@kcore.org> */
UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
"CITIZEN",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index e268aacb773..bfea851be98 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,7 +1,5 @@
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
@@ -312,26 +310,27 @@ static int usb_stor_control_thread(void * __us)
for(;;) {
US_DEBUGP("*** thread sleeping.\n");
- if(down_interruptible(&us->sema))
+ if (wait_for_completion_interruptible(&us->cmnd_ready))
break;
-
+
US_DEBUGP("*** thread awakened.\n");
/* lock the device pointers */
mutex_lock(&(us->dev_mutex));
- /* if the device has disconnected, we are free to exit */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- US_DEBUGP("-- exiting\n");
+ /* lock access to the state */
+ scsi_lock(host);
+
+ /* When we are called with no command pending, we're done */
+ if (us->srb == NULL) {
+ scsi_unlock(host);
mutex_unlock(&us->dev_mutex);
+ US_DEBUGP("-- exiting\n");
break;
}
- /* lock access to the state */
- scsi_lock(host);
-
/* has the command timed out *already* ? */
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
us->srb->result = DID_ABORT << 16;
goto SkipForAbort;
}
@@ -350,7 +349,7 @@ static int usb_stor_control_thread(void * __us)
* the maximum known LUN
*/
else if (us->srb->device->id &&
- !(us->flags & US_FL_SCM_MULT_TARG)) {
+ !(us->fflags & US_FL_SCM_MULT_TARG)) {
US_DEBUGP("Bad target number (%d:%d)\n",
us->srb->device->id, us->srb->device->lun);
us->srb->result = DID_BAD_TARGET << 16;
@@ -365,7 +364,7 @@ static int usb_stor_control_thread(void * __us)
/* Handle those devices which need us to fake
* their inquiry data */
else if ((us->srb->cmnd[0] == INQUIRY) &&
- (us->flags & US_FL_FIX_INQUIRY)) {
+ (us->fflags & US_FL_FIX_INQUIRY)) {
unsigned char data_ptr[36] = {
0x00, 0x80, 0x02, 0x02,
0x1F, 0x00, 0x00, 0x00};
@@ -384,12 +383,8 @@ static int usb_stor_control_thread(void * __us)
/* lock access to the state */
scsi_lock(host);
- /* did the command already complete because of a disconnect? */
- if (!us->srb)
- ; /* nothing to do */
-
/* indicate that the command is done */
- else if (us->srb->result != DID_ABORT << 16) {
+ if (us->srb->result != DID_ABORT << 16) {
US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
us->srb->scsi_done(us->srb);
@@ -403,12 +398,12 @@ SkipForAbort:
* the TIMED_OUT flag, not srb->result == DID_ABORT, because
* the timeout might have occurred after the command had
* already completed with a different result code. */
- if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+ if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
complete(&(us->notify));
/* Allow USB transfers to resume */
- clear_bit(US_FLIDX_ABORTING, &us->flags);
- clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+ clear_bit(US_FLIDX_ABORTING, &us->dflags);
+ clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
}
/* finished working on this command */
@@ -500,9 +495,9 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
- us->flags = USB_US_ORIG_FLAGS(id->driver_info);
+ us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
- if (us->flags & US_FL_IGNORE_DEVICE) {
+ if (us->fflags & US_FL_IGNORE_DEVICE) {
printk(KERN_INFO USB_STORAGE "device ignored\n");
return -ENODEV;
}
@@ -512,7 +507,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
* disable it if we're in full-speed
*/
if (dev->speed != USB_SPEED_HIGH)
- us->flags &= ~US_FL_GO_SLOW;
+ us->fflags &= ~US_FL_GO_SLOW;
/* Log a message if a non-generic unusual_dev entry contains an
* unnecessary subclass or protocol override. This may stimulate
@@ -533,7 +528,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == idesc->bInterfaceProtocol)
msg += 2;
- if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
+ if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x,%04x S %02x P %02x)"
" has %s in unusual_devs.h (kernel"
@@ -663,7 +658,7 @@ static int get_transport(struct us_data *us)
US_DEBUGP("Transport: %s\n", us->transport_name);
/* fix for single-lun devices */
- if (us->flags & US_FL_SINGLE_LUN)
+ if (us->fflags & US_FL_SINGLE_LUN)
us->max_lun = 0;
return 0;
}
@@ -820,12 +815,11 @@ static void usb_stor_release_resources(struct us_data *us)
US_DEBUGP("-- %s\n", __func__);
/* Tell the control thread to exit. The SCSI host must
- * already have been removed so it won't try to queue
- * any more commands.
+ * already have been removed and the DISCONNECTING flag set
+ * so that we won't accept any more commands.
*/
US_DEBUGP("-- sending exit command to thread\n");
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- up(&us->sema);
+ complete(&us->cmnd_ready);
if (us->ctl_thread)
kthread_stop(us->ctl_thread);
@@ -859,39 +853,36 @@ static void dissociate_dev(struct us_data *us)
usb_set_intfdata(us->pusb_intf, NULL);
}
-/* First stage of disconnect processing: stop all commands and remove
- * the host */
+/* First stage of disconnect processing: stop SCSI scanning,
+ * remove the host, and stop accepting new commands
+ */
static void quiesce_and_remove_host(struct us_data *us)
{
struct Scsi_Host *host = us_to_host(us);
- /* Prevent new USB transfers, stop the current command, and
- * interrupt a SCSI-scan or device-reset delay */
- scsi_lock(host);
- set_bit(US_FLIDX_DISCONNECTING, &us->flags);
- scsi_unlock(host);
- usb_stor_stop_transport(us);
- wake_up(&us->delay_wait);
+ /* If the device is really gone, cut short reset delays */
+ if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+ set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
- /* queuecommand won't accept any new commands and the control
- * thread won't execute a previously-queued command. If there
- * is such a command pending, complete it with an error. */
- mutex_lock(&us->dev_mutex);
- if (us->srb) {
- us->srb->result = DID_NO_CONNECT << 16;
- scsi_lock(host);
- us->srb->scsi_done(us->srb);
- us->srb = NULL;
- complete(&us->notify); /* in case of an abort */
- scsi_unlock(host);
- }
- mutex_unlock(&us->dev_mutex);
+ /* Prevent SCSI-scanning (if it hasn't started yet)
+ * and wait for the SCSI-scanning thread to stop.
+ */
+ set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
+ wake_up(&us->delay_wait);
+ wait_for_completion(&us->scanning_done);
- /* Now we own no commands so it's safe to remove the SCSI host */
+ /* Removing the host will perform an orderly shutdown: caches
+ * synchronized, disks spun down, etc.
+ */
scsi_remove_host(host);
- /* Wait for the SCSI-scanning thread to stop */
- wait_for_completion(&us->scanning_done);
+ /* Prevent any new commands from being accepted and cut short
+ * reset delays.
+ */
+ scsi_lock(host);
+ set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ scsi_unlock(host);
+ wake_up(&us->delay_wait);
}
/* Second stage of disconnect processing: deallocate all resources */
@@ -919,16 +910,16 @@ static int usb_stor_scan_thread(void * __us)
printk(KERN_DEBUG "usb-storage: waiting for device "
"to settle before scanning\n");
wait_event_freezable_timeout(us->delay_wait,
- test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+ test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
delay_use * HZ);
}
/* If the device is still connected, perform the scanning */
- if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
/* For bulk-only devices, determine the max LUN value */
if (us->protocol == US_PR_BULK &&
- !(us->flags & US_FL_SINGLE_LUN)) {
+ !(us->fflags & US_FL_SINGLE_LUN)) {
mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex);
@@ -975,7 +966,7 @@ static int storage_probe(struct usb_interface *intf,
us = host_to_us(host);
memset(us, 0, sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
- init_MUTEX_LOCKED(&(us->sema));
+ init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
init_completion(&us->scanning_done);
@@ -1023,6 +1014,7 @@ static int storage_probe(struct usb_interface *intf,
if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
+ complete(&us->scanning_done);
quiesce_and_remove_host(us);
result = PTR_ERR(th);
goto BadDevice;
@@ -1065,6 +1057,7 @@ static struct usb_driver usb_storage_driver = {
.pre_reset = storage_pre_reset,
.post_reset = storage_post_reset,
.id_table = storage_usb_ids,
+ .soft_unbind = 1,
};
static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 8d87503e256..a4ad73bd832 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -1,8 +1,6 @@
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
- * $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $
- *
* Current development and maintenance by:
* (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
@@ -67,16 +65,14 @@ struct us_unusual_dev {
};
-/* Dynamic flag definitions: used in set_bit() etc. */
-#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
-#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */
-#define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */
-#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
-#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \
- (1UL << US_FLIDX_DISCONNECTING))
-#define US_FLIDX_RESETTING 22 /* 0x00400000 device reset in progress */
-#define US_FLIDX_TIMED_OUT 23 /* 0x00800000 SCSI midlayer timed out */
-
+/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */
+#define US_FLIDX_URB_ACTIVE 0 /* current_urb is in use */
+#define US_FLIDX_SG_ACTIVE 1 /* current_sg is in use */
+#define US_FLIDX_ABORTING 2 /* abort is in progress */
+#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */
+#define US_FLIDX_RESETTING 4 /* device reset in progress */
+#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
+#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
#define USB_STOR_STRING_LEN 32
@@ -109,7 +105,8 @@ struct us_data {
struct usb_device *pusb_dev; /* this usb_device */
struct usb_interface *pusb_intf; /* this interface */
struct us_unusual_dev *unusual_dev; /* device-filter entry */
- unsigned long flags; /* from filter initially */
+ unsigned long fflags; /* fixed flags from filter */
+ unsigned long dflags; /* dynamic atomic bitflags */
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
unsigned int send_ctrl_pipe;
@@ -147,7 +144,7 @@ struct us_data {
struct task_struct *ctl_thread; /* the control thread */
/* mutual exclusion and synchronization structures */
- struct semaphore sema; /* to sleep thread on */
+ struct completion cmnd_ready; /* to sleep thread on */
struct completion notify; /* thread begin/end */
wait_queue_head_t delay_wait; /* wait during scan, reset */
struct completion scanning_done; /* wait for scan thread */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9b887ef64ff..70d135e0cc4 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1658,6 +1658,32 @@ config FB_PM3
similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
and maybe other boards.
+config FB_CARMINE
+ tristate "Fujitsu carmine frame buffer support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This is the frame buffer device driver for the Fujitsu Carmine chip.
+ The driver provides two independent frame buffer devices.
+
+choice
+ depends on FB_CARMINE
+ prompt "DRAM timing"
+ default FB_CARMINE_DRAM_EVAL
+
+config FB_CARMINE_DRAM_EVAL
+ bool "Eval board timings"
+ help
+ Use timings which work on the eval card.
+
+config CARMINE_DRAM_CUSTOM
+ bool "Custom board timings"
+ help
+ Use custom board timings.
+endchoice
+
config FB_AU1100
bool "Au1100 LCD Driver"
depends on (FB = y) && MIPS && SOC_AU1100
@@ -1840,6 +1866,16 @@ config FB_W100
If unsure, say N.
+config FB_SH_MOBILE_LCDC
+ tristate "SuperH Mobile LCDC framebuffer support"
+ depends on FB && SUPERH
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ default m
+ ---help---
+ Frame buffer driver for the on-chip SH-Mobile LCD controller.
+
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
depends on FB && ARCH_S3C2410
@@ -1951,6 +1987,23 @@ config FB_AM200EPD
This enables support for the Metronome display controller used on
the E-Ink AM-200 EPD devkit.
+config FB_COBALT
+ tristate "Cobalt server LCD frame buffer support"
+ depends on FB && MIPS_COBALT
+
+config FB_SH7760
+ bool "SH7760/SH7763 LCDC support"
+ depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Support for the SH7760/SH7763 integrated (D)STN/TFT LCD Controller.
+ Supports display resolutions up to 1024x1024 pixel, grayscale and
+ color operation, with depths ranging from 1 bpp to 8 bpp monochrome
+ and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
+ panels <= 320 pixel horizontal resolution.
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 04bca35403f..0ebc1bfd251 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -106,17 +106,22 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_METRONOME) += metronomefb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
+obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
+obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
+obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
+obj-$(CONFIG_FB_SH7343VOU) += sh7343_voufb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
+obj-$(CONFIG_FB_CARMINE) += carminefb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index eedb8285e32..017233d0c48 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/platform_device.h>
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 45c154ade9c..b8e9a8682f2 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1136,7 +1136,6 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg
* Interface to the low level console driver
*/
-int amifb_init(void);
static void amifb_deinit(void);
/*
@@ -2048,13 +2047,16 @@ static void amifb_copyarea(struct fb_info *info,
width = x2 - dx;
height = y2 - dy;
+ if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+ return;
+
/* update sx,sy */
sx = area->sx + (dx - area->dx);
sy = area->sy + (dy - area->dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
- (sy + height) > info->var.yres_virtual)
+ if (sx + width > info->var.xres_virtual ||
+ sy + height > info->var.yres_virtual)
return;
if (dy > sy || (dy == sy && dx > sx)) {
@@ -2245,7 +2247,7 @@ static inline void chipfree(void)
* Initialisation
*/
-int __init amifb_init(void)
+static int __init amifb_init(void)
{
int tag, i, err = 0;
u_long chipptr;
@@ -3790,16 +3792,14 @@ static void ami_rebuild_copper(void)
}
}
-
-module_init(amifb_init);
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-void cleanup_module(void)
+static void __exit amifb_exit(void)
{
unregister_framebuffer(&fb_info);
amifb_deinit();
amifb_video_off();
}
-#endif /* MODULE */
+
+module_init(amifb_init);
+module_exit(amifb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index fa55d356b53..77eb8b34fbf 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2593,13 +2593,16 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
width = x2 - dx;
height = y2 - dy;
+ if (area->sx + dx < area->dx || area->sy + dy < area->dy)
+ return;
+
/* update sx,sy */
sx = area->sx + (dx - area->dx);
sy = area->sy + (dy - area->dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
- (sy + height) > info->var.yres_virtual)
+ if (sx + width > info->var.xres_virtual ||
+ sy + height > info->var.yres_virtual)
return;
if (dy > sy || (dy == sy && dx > sx)) {
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index b004036d408..5b3a15dffb5 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -256,6 +256,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
return 0;
}
+static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_videomode varfbmode;
+ const struct fb_videomode *fbmode = NULL;
+
+ fb_var_to_videomode(&varfbmode, var);
+ fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
+ if (fbmode)
+ fb_videomode_to_var(var, fbmode);
+ return fbmode;
+}
+
+
/**
* atmel_lcdfb_check_var - Validates a var passed in.
* @var: frame buffer variable screen structure
@@ -289,6 +303,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
dev_dbg(dev, "%s:\n", __func__);
+
+ if (!(var->pixclock && var->bits_per_pixel)) {
+ /* choose a suitable mode if possible */
+ if (!atmel_lcdfb_choose_mode(var, info)) {
+ dev_err(dev, "needed value not specified\n");
+ return -EINVAL;
+ }
+ }
+
dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
@@ -299,6 +322,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
+ /* Do not allow to have real resoulution larger than virtual */
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
/* Force same alignment for each line */
var->xres = (var->xres + 3) & ~3UL;
var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
@@ -379,6 +409,35 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
return 0;
}
+/*
+ * LCD reset sequence
+ */
+static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
+{
+ might_sleep();
+
+ /* LCD power off */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+ /* wait for the LCDC core to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
+ msleep(10);
+
+ /* DMA disable */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+ /* wait for DMA engine to become idle */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+ msleep(10);
+
+ /* LCD power on */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+ /* DMA enable */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+}
+
/**
* atmel_lcdfb_set_par - Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
@@ -401,6 +460,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
unsigned long clk_value_khz;
unsigned long bits_per_line;
+ might_sleep();
+
dev_dbg(info->device, "%s:\n", __func__);
dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
info->var.xres, info->var.yres,
@@ -511,6 +572,8 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
/* Disable all interrupts */
lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+ /* Enable FIFO & DMA errors */
+ lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
/* ...wait for DMA engine to become idle... */
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
@@ -645,10 +708,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
u32 status;
status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
- lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+ if (status & ATMEL_LCDC_UFLWI) {
+ dev_warn(info->device, "FIFO underflow %#x\n", status);
+ /* reset DMA and FIFO to avoid screen shifting */
+ schedule_work(&sinfo->task);
+ }
+ lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
return IRQ_HANDLED;
}
+/*
+ * LCD controller task (to reset the LCD)
+ */
+static void atmel_lcdfb_task(struct work_struct *work)
+{
+ struct atmel_lcdfb_info *sinfo =
+ container_of(work, struct atmel_lcdfb_info, task);
+
+ atmel_lcdfb_reset(sinfo);
+}
+
static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
{
struct fb_info *info = sinfo->info;
@@ -691,6 +770,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct atmel_lcdfb_info *sinfo;
struct atmel_lcdfb_info *pdata_sinfo;
+ struct fb_videomode fbmode;
struct resource *regs = NULL;
struct resource *map = NULL;
int ret;
@@ -824,6 +904,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto unmap_mmio;
}
+ /* Some operations on the LCDC might sleep and
+ * require a preemptible task context */
+ INIT_WORK(&sinfo->task, atmel_lcdfb_task);
+
ret = atmel_lcdfb_init_fbinfo(sinfo);
if (ret < 0) {
dev_err(dev, "init fbinfo failed: %d\n", ret);
@@ -853,6 +937,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto free_cmap;
}
+ /* add selected videomode to modelist */
+ fb_var_to_videomode(&fbmode, &info->var);
+ fb_add_videomode(&fbmode, &info->modelist);
+
/* Power up the LCDC screen */
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(1);
@@ -866,6 +954,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
free_cmap:
fb_dealloc_cmap(&info->cmap);
unregister_irqs:
+ cancel_work_sync(&sinfo->task);
free_irq(sinfo->irq_base, info);
unmap_mmio:
exit_backlight(sinfo);
@@ -903,6 +992,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
if (!sinfo)
return 0;
+ cancel_work_sync(&sinfo->task);
exit_backlight(sinfo);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 24ee96c4e9e..243ea4ab20c 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1339,10 +1339,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
if (vclk * 12 < c.ppll_min)
vclk = c.ppll_min/12;
- pll->post_divider = -1;
-
/* now, find an acceptable divider */
- for (i = 0; i < sizeof(post_dividers); i++) {
+ for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
output_freq = post_dividers[i] * vclk;
if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
pll->post_divider = post_dividers[i];
@@ -1350,7 +1348,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
}
}
- if (pll->post_divider < 0)
+ if (i == ARRAY_SIZE(post_dividers))
return -EINVAL;
/* calculate feedback divider */
@@ -1872,7 +1870,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
struct fb_var_screeninfo var;
- char video_card[DEVICE_NAME_SIZE];
+ char video_card[50];
u8 chip_rev;
u32 dac;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index bd4ac0bafec..620ba812036 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -424,7 +424,6 @@ static struct {
#endif /* CONFIG_FB_ATY_CT */
};
-/* can not fail */
static int __devinit correct_chipset(struct atyfb_par *par)
{
u8 rev;
@@ -437,6 +436,9 @@ static int __devinit correct_chipset(struct atyfb_par *par)
if (par->pci_id == aty_chips[i].pci_id)
break;
+ if (i < 0)
+ return -ENODEV;
+
name = aty_chips[i].name;
par->pll_limits.pll_max = aty_chips[i].pll;
par->pll_limits.mclk = aty_chips[i].mclk;
@@ -2229,6 +2231,7 @@ static int __devinit aty_init(struct fb_info *info)
const char *ramname = NULL, *xtal;
int gtb_memsize, has_var = 0;
struct fb_var_screeninfo var;
+ int ret;
init_waitqueue_head(&par->vblank.wait);
spin_lock_init(&par->int_lock);
@@ -2610,7 +2613,8 @@ static int __devinit aty_init(struct fb_info *info)
var.yres_virtual = var.yres;
}
- if (atyfb_check_var(&var, info)) {
+ ret = atyfb_check_var(&var, info);
+ if (ret) {
PRINTKE("can't set default video mode\n");
goto aty_init_exit;
}
@@ -2621,10 +2625,12 @@ static int __devinit aty_init(struct fb_info *info)
#endif /* CONFIG_FB_ATY_CT */
info->var = var;
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret < 0)
goto aty_init_exit;
- if (register_framebuffer(info) < 0) {
+ ret = register_framebuffer(info);
+ if (ret < 0) {
fb_dealloc_cmap(&info->cmap);
goto aty_init_exit;
}
@@ -2650,7 +2656,7 @@ aty_init_exit:
par->mtrr_aper = -1;
}
#endif
- return -1;
+ return ret;
}
static void aty_resume_chip(struct fb_info *info)
@@ -2709,8 +2715,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
if (par->lock_blank || par->asleep)
return 0;
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -2739,8 +2744,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
}
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
-#ifdef CONFIG_FB_ATY_BACKLIGHT
-#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -3331,7 +3335,7 @@ static int __devinit init_from_bios(struct atyfb_par *par)
PRINTKE("no BIOS frequency table found, use parameters\n");
ret = -ENXIO;
}
- iounmap((void* __iomem )bios_base);
+ iounmap((void __iomem *)bios_base);
return ret;
}
@@ -3418,14 +3422,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
struct fb_info *info;
struct resource *rp;
struct atyfb_par *par;
- int i, rc = -ENOMEM;
-
- for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
- if (pdev->device == aty_chips[i].pci_id)
- break;
-
- if (i < 0)
- return -ENODEV;
+ int rc = -ENOMEM;
/* Enable device in PCI config */
if (pci_enable_device(pdev)) {
@@ -3456,7 +3453,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
par = info->par;
info->fix = atyfb_fix;
info->device = &pdev->dev;
- par->pci_id = aty_chips[i].pci_id;
+ par->pci_id = pdev->device;
par->res_start = res_start;
par->res_size = res_size;
par->irq = pdev->irq;
@@ -3474,7 +3471,8 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
pci_set_drvdata(pdev, info);
/* Init chip & register framebuffer */
- if (aty_init(info))
+ rc = aty_init(info);
+ if (rc)
goto err_release_io;
#ifdef __sparc__
@@ -3655,18 +3653,62 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
atyfb_remove(info);
}
-/*
- * This driver uses its own matching table. That will be more difficult
- * to fix, so for now, we just match against any ATI ID and let the
- * probe() function find out what's up. That also mean we don't have
- * a module ID table though.
- */
static struct pci_device_id atyfb_pci_tbl[] = {
- { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
- PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
- { 0, }
+#ifdef CONFIG_FB_ATY_GX
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
+#endif /* CONFIG_FB_ATY_GX */
+
+#ifdef CONFIG_FB_ATY_CT
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
+
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
+#endif /* CONFIG_FB_ATY_CT */
+ { }
};
+MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
+
static struct pci_driver atyfb_driver = {
.name = "atyfb",
.id_table = atyfb_pci_tbl,
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 400e9264e45..652273e9f5f 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2098,15 +2098,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
{
- if (off > EDID_LENGTH)
- return 0;
-
- if (off + count > EDID_LENGTH)
- count = EDID_LENGTH - off;
-
- memcpy(buf, edid + off, count);
-
- return count;
+ return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
}
@@ -2161,6 +2153,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
struct radeonfb_info *rinfo;
int ret;
unsigned char c1, c2;
+ int err = 0;
pr_debug("radeonfb_pci_register BEGIN\n");
@@ -2340,9 +2333,14 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
/* Register some sysfs stuff (should be done better) */
if (rinfo->mon1_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+ err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+ &edid1_attr);
if (rinfo->mon2_EDID)
- sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+ err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
+ &edid2_attr);
+ if (err)
+ pr_warning("%s() Creating sysfs files failed, continuing\n",
+ __func__);
/* save current mode regs before we switch into the new one
* so we can restore this upon __exit
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index c347e38cd0b..ccbfffd1280 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -289,7 +289,7 @@ struct radeonfb_info {
struct radeon_regs state;
struct radeon_regs init_state;
- char name[DEVICE_NAME_SIZE];
+ char name[50];
unsigned long mmio_base_phys;
unsigned long fb_base_phys;
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 30bf7f2f163..452b770d8cc 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -36,6 +36,30 @@ config LCD_LTV350QV
The LTV350QV panel is present on all ATSTK1000 boards.
+config LCD_ILI9320
+ tristate
+ depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
+ default n
+ help
+ If you have a panel based on the ILI9320 controller chip
+ then say y to include a power driver for it.
+
+config LCD_VGG2432A4
+ tristate "VGG2432A4 LCM device support"
+ depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
+ select LCD_ILI9320
+ default n
+ help
+ If you have a VGG2432A4 panel based on the ILI9320 controller chip
+ then say y to include a power driver for it.
+
+config LCD_PLATFORM
+ tristate "Platform LCD controls"
+ depends on LCD_CLASS_DEVICE
+ help
+ This driver provides a platform-device registered LCD power
+ control interface.
+
#
# Backlight
#
@@ -63,6 +87,18 @@ config BACKLIGHT_ATMEL_LCDC
If in doubt, it's safe to enable this option; it doesn't kick
in unless the board's description says it's wired that way.
+config BACKLIGHT_ATMEL_PWM
+ tristate "Atmel PWM backlight control"
+ depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM
+ default n
+ help
+ Say Y here if you want to use the PWM peripheral in Atmel AT91 and
+ AVR32 devices. This driver will need additional platform data to know
+ which PWM instance to use and how to configure it.
+
+ To compile this driver as a module, choose M here: the module will be
+ called atmel-pwm-bl.
+
config BACKLIGHT_CORGI
tristate "Generic (aka Sharp Corgi) Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE
@@ -119,3 +155,12 @@ config BACKLIGHT_PWM
help
If you have a LCD backlight adjustable by PWM, say Y to enable
this driver.
+
+config BACKLIGHT_MBP_NVIDIA
+ tristate "MacBook Pro Nvidia Backlight Driver"
+ depends on BACKLIGHT_CLASS_DEVICE && X86
+ default n
+ help
+ If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
+ to enable a driver for its backlight
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index b51a7cd1250..b405aace803 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -1,9 +1,13 @@
# Backlight & LCD drivers
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
-obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
+obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
+obj-$(CONFIG_LCD_ILI9320) += ili9320.o
+obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
+obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
+obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
@@ -11,3 +15,5 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
+obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
+
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
new file mode 100644
index 00000000000..505c0823a10
--- /dev/null
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * Backlight driver using Atmel PWM peripheral.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/backlight.h>
+#include <linux/atmel_pwm.h>
+#include <linux/atmel-pwm-bl.h>
+
+struct atmel_pwm_bl {
+ const struct atmel_pwm_bl_platform_data *pdata;
+ struct backlight_device *bldev;
+ struct platform_device *pdev;
+ struct pwm_channel pwmc;
+ int gpio_on;
+};
+
+static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
+{
+ struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+ int intensity = bd->props.brightness;
+ int pwm_duty;
+
+ if (bd->props.power != FB_BLANK_UNBLANK)
+ intensity = 0;
+ if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+ intensity = 0;
+
+ if (pwmbl->pdata->pwm_active_low)
+ pwm_duty = pwmbl->pdata->pwm_duty_min + intensity;
+ else
+ pwm_duty = pwmbl->pdata->pwm_duty_max - intensity;
+
+ if (pwm_duty > pwmbl->pdata->pwm_duty_max)
+ pwm_duty = pwmbl->pdata->pwm_duty_max;
+ if (pwm_duty < pwmbl->pdata->pwm_duty_min)
+ pwm_duty = pwmbl->pdata->pwm_duty_min;
+
+ if (!intensity) {
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on,
+ 0 ^ pwmbl->pdata->on_active_low);
+ }
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+ pwm_channel_disable(&pwmbl->pwmc);
+ } else {
+ pwm_channel_enable(&pwmbl->pwmc);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on,
+ 1 ^ pwmbl->pdata->on_active_low);
+ }
+ }
+
+ return 0;
+}
+
+static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
+{
+ struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
+ u8 intensity;
+
+ if (pwmbl->pdata->pwm_active_low) {
+ intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) -
+ pwmbl->pdata->pwm_duty_min;
+ } else {
+ intensity = pwmbl->pdata->pwm_duty_max -
+ pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
+ }
+
+ return intensity;
+}
+
+static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
+{
+ unsigned long pwm_rate = pwmbl->pwmc.mck;
+ unsigned long prescale = DIV_ROUND_UP(pwm_rate,
+ (pwmbl->pdata->pwm_frequency *
+ pwmbl->pdata->pwm_compare_max)) - 1;
+
+ /*
+ * Prescale must be power of two and maximum 0xf in size because of
+ * hardware limit. PWM speed will be:
+ * PWM module clock speed / (2 ^ prescale).
+ */
+ prescale = fls(prescale);
+ if (prescale > 0xf)
+ prescale = 0xf;
+
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY,
+ pwmbl->pdata->pwm_duty_min +
+ pwmbl->bldev->props.brightness);
+ pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
+ pwmbl->pdata->pwm_compare_max);
+
+ dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
+ "(%lu Hz)\n", pwmbl->pwmc.mck /
+ pwmbl->pdata->pwm_compare_max /
+ (1 << prescale));
+
+ return pwm_channel_enable(&pwmbl->pwmc);
+}
+
+static struct backlight_ops atmel_pwm_bl_ops = {
+ .get_brightness = atmel_pwm_bl_get_intensity,
+ .update_status = atmel_pwm_bl_set_intensity,
+};
+
+static int atmel_pwm_bl_probe(struct platform_device *pdev)
+{
+ const struct atmel_pwm_bl_platform_data *pdata;
+ struct backlight_device *bldev;
+ struct atmel_pwm_bl *pwmbl;
+ int retval;
+
+ pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL);
+ if (!pwmbl)
+ return -ENOMEM;
+
+ pwmbl->pdev = pdev;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ retval = -ENODEV;
+ goto err_free_mem;
+ }
+
+ if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
+ pdata->pwm_duty_min > pdata->pwm_duty_max ||
+ pdata->pwm_frequency == 0) {
+ retval = -EINVAL;
+ goto err_free_mem;
+ }
+
+ pwmbl->pdata = pdata;
+ pwmbl->gpio_on = pdata->gpio_on;
+
+ retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
+ if (retval)
+ goto err_free_mem;
+
+ if (pwmbl->gpio_on != -1) {
+ retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl");
+ if (retval) {
+ pwmbl->gpio_on = -1;
+ goto err_free_pwm;
+ }
+
+ /* Turn display off by defatult. */
+ retval = gpio_direction_output(pwmbl->gpio_on,
+ 0 ^ pdata->on_active_low);
+ if (retval)
+ goto err_free_gpio;
+ }
+
+ bldev = backlight_device_register("atmel-pwm-bl",
+ &pdev->dev, pwmbl, &atmel_pwm_bl_ops);
+ if (IS_ERR(bldev)) {
+ retval = PTR_ERR(bldev);
+ goto err_free_gpio;
+ }
+
+ pwmbl->bldev = bldev;
+
+ platform_set_drvdata(pdev, pwmbl);
+
+ /* Power up the backlight by default at middle intesity. */
+ bldev->props.power = FB_BLANK_UNBLANK;
+ bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
+ bldev->props.brightness = bldev->props.max_brightness / 2;
+
+ retval = atmel_pwm_bl_init_pwm(pwmbl);
+ if (retval)
+ goto err_free_bl_dev;
+
+ atmel_pwm_bl_set_intensity(bldev);
+
+ return 0;
+
+err_free_bl_dev:
+ platform_set_drvdata(pdev, NULL);
+ backlight_device_unregister(bldev);
+err_free_gpio:
+ if (pwmbl->gpio_on != -1)
+ gpio_free(pwmbl->gpio_on);
+err_free_pwm:
+ pwm_channel_free(&pwmbl->pwmc);
+err_free_mem:
+ kfree(pwmbl);
+ return retval;
+}
+
+static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
+{
+ struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
+
+ if (pwmbl->gpio_on != -1) {
+ gpio_set_value(pwmbl->gpio_on, 0);
+ gpio_free(pwmbl->gpio_on);
+ }
+ pwm_channel_disable(&pwmbl->pwmc);
+ pwm_channel_free(&pwmbl->pwmc);
+ backlight_device_unregister(pwmbl->bldev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(pwmbl);
+
+ return 0;
+}
+
+static struct platform_driver atmel_pwm_bl_driver = {
+ .driver = {
+ .name = "atmel-pwm-bl",
+ },
+ /* REVISIT add suspend() and resume() */
+ .remove = __exit_p(atmel_pwm_bl_remove),
+};
+
+static int __init atmel_pwm_bl_init(void)
+{
+ return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
+}
+module_init(atmel_pwm_bl_init);
+
+static void __exit atmel_pwm_bl_exit(void)
+{
+ platform_driver_unregister(&atmel_pwm_bl_driver);
+}
+module_exit(atmel_pwm_bl_exit);
+
+MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
+MODULE_DESCRIPTION("Atmel PWM backlight driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 39394757679..fab0bc874b5 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -191,6 +191,7 @@ static struct device_attribute bl_device_attributes[] = {
* backlight_device class.
* @name: the name of the new object(must be the same as the name of the
* respective framebuffer device).
+ * @parent: a pointer to the parent device
* @devdata: an optional pointer to be stored for private driver use. The
* methods may retrieve it by using bl_get_data(bd).
* @ops: the backlight operations structure.
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
new file mode 100644
index 00000000000..ba89b41b639
--- /dev/null
+++ b/drivers/video/backlight/ili9320.c
@@ -0,0 +1,330 @@
+/* drivers/video/backlight/ili9320.c
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+
+static inline int ili9320_write_spi(struct ili9320 *ili,
+ unsigned int reg,
+ unsigned int value)
+{
+ struct ili9320_spi *spi = &ili->access.spi;
+ unsigned char *addr = spi->buffer_addr;
+ unsigned char *data = spi->buffer_data;
+
+ /* spi message consits of:
+ * first byte: ID and operation
+ */
+
+ addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE;
+ addr[1] = reg >> 8;
+ addr[2] = reg;
+
+ /* second message is the data to transfer */
+
+ data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE;
+ data[1] = value >> 8;
+ data[2] = value;
+
+ return spi_sync(spi->dev, &spi->message);
+}
+
+int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
+{
+ dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
+ return ili->write(ili, reg, value);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write);
+
+int ili9320_write_regs(struct ili9320 *ili,
+ struct ili9320_reg *values,
+ int nr_values)
+{
+ int index;
+ int ret;
+
+ for (index = 0; index < nr_values; index++, values++) {
+ ret = ili9320_write(ili, values->address, values->value);
+ if (ret != 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write_regs);
+
+static void ili9320_reset(struct ili9320 *lcd)
+{
+ struct ili9320_platdata *cfg = lcd->platdata;
+
+ cfg->reset(1);
+ mdelay(50);
+
+ cfg->reset(0);
+ mdelay(50);
+
+ cfg->reset(1);
+ mdelay(100);
+}
+
+static inline int ili9320_init_chip(struct ili9320 *lcd)
+{
+ int ret;
+
+ ili9320_reset(lcd);
+
+ ret = lcd->client->init(lcd, lcd->platdata);
+ if (ret != 0) {
+ dev_err(lcd->dev, "failed to initialise display\n");
+ return ret;
+ }
+
+ lcd->initialised = 1;
+ return 0;
+}
+
+static inline int ili9320_power_on(struct ili9320 *lcd)
+{
+ if (!lcd->initialised)
+ ili9320_init_chip(lcd);
+
+ lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+}
+
+static inline int ili9320_power_off(struct ili9320 *lcd)
+{
+ lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+}
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+static int ili9320_power(struct ili9320 *lcd, int power)
+{
+ int ret = 0;
+
+ dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power);
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+ ret = ili9320_power_on(lcd);
+ else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+ ret = ili9320_power_off(lcd);
+
+ if (ret == 0)
+ lcd->power = power;
+ else
+ dev_warn(lcd->dev, "failed to set power mode %d\n", power);
+
+ return ret;
+}
+
+static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd)
+{
+ return lcd_get_data(lcd);
+}
+
+static int ili9320_set_power(struct lcd_device *ld, int power)
+{
+ struct ili9320 *lcd = to_our_lcd(ld);
+
+ return ili9320_power(lcd, power);
+}
+
+static int ili9320_get_power(struct lcd_device *ld)
+{
+ struct ili9320 *lcd = to_our_lcd(ld);
+
+ return lcd->power;
+}
+
+static struct lcd_ops ili9320_ops = {
+ .get_power = ili9320_get_power,
+ .set_power = ili9320_set_power,
+};
+
+static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+ struct spi_device *dev)
+{
+ struct ili9320_spi *spi = &ili->access.spi;
+
+ ili->write = ili9320_write_spi;
+ spi->dev = dev;
+
+ /* fill the two messages we are going to use to send the data
+ * with, the first the address followed by the data. The datasheet
+ * says they should be done as two distinct cycles of the SPI CS line.
+ */
+
+ spi->xfer[0].tx_buf = spi->buffer_addr;
+ spi->xfer[1].tx_buf = spi->buffer_data;
+ spi->xfer[0].len = 3;
+ spi->xfer[1].len = 3;
+ spi->xfer[0].bits_per_word = 8;
+ spi->xfer[1].bits_per_word = 8;
+ spi->xfer[0].cs_change = 1;
+
+ spi_message_init(&spi->message);
+ spi_message_add_tail(&spi->xfer[0], &spi->message);
+ spi_message_add_tail(&spi->xfer[1], &spi->message);
+}
+
+int __devinit ili9320_probe_spi(struct spi_device *spi,
+ struct ili9320_client *client)
+{
+ struct ili9320_platdata *cfg = spi->dev.platform_data;
+ struct device *dev = &spi->dev;
+ struct ili9320 *ili;
+ struct lcd_device *lcd;
+ int ret = 0;
+
+ /* verify we where given some information */
+
+ if (cfg == NULL) {
+ dev_err(dev, "no platform data supplied\n");
+ return -EINVAL;
+ }
+
+ if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
+ dev_err(dev, "invalid platform data supplied\n");
+ return -EINVAL;
+ }
+
+ /* allocate and initialse our state */
+
+ ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
+ if (ili == NULL) {
+ dev_err(dev, "no memory for device\n");
+ return -ENOMEM;
+ }
+
+ ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
+
+ ili->dev = dev;
+ ili->client = client;
+ ili->power = FB_BLANK_POWERDOWN;
+ ili->platdata = cfg;
+
+ dev_set_drvdata(&spi->dev, ili);
+
+ ili9320_setup_spi(ili, spi);
+
+ lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
+ if (IS_ERR(lcd)) {
+ dev_err(dev, "failed to register lcd device\n");
+ ret = PTR_ERR(lcd);
+ goto err_free;
+ }
+
+ ili->lcd = lcd;
+
+ dev_info(dev, "initialising %s\n", client->name);
+
+ ret = ili9320_power(ili, FB_BLANK_UNBLANK);
+ if (ret != 0) {
+ dev_err(dev, "failed to set lcd power state\n");
+ goto err_unregister;
+ }
+
+ return 0;
+
+ err_unregister:
+ lcd_device_unregister(lcd);
+
+ err_free:
+ kfree(ili);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_probe_spi);
+
+int __devexit ili9320_remove(struct ili9320 *ili)
+{
+ ili9320_power(ili, FB_BLANK_POWERDOWN);
+
+ lcd_device_unregister(ili->lcd);
+ kfree(ili);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_remove);
+
+#ifdef CONFIG_PM
+int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
+{
+ int ret;
+
+ dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event);
+
+ if (state.event == PM_EVENT_SUSPEND) {
+ ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
+
+ if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+ ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
+ ILI9320_POWER1_SLP |
+ ILI9320_POWER1_DSTB);
+ lcd->initialised = 0;
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_suspend);
+
+int ili9320_resume(struct ili9320 *lcd)
+{
+ dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
+
+ if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+ ili9320_write(lcd, ILI9320_POWER1, 0x00);
+ }
+
+ return ili9320_power(lcd, FB_BLANK_UNBLANK);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_resume);
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+void ili9320_shutdown(struct ili9320 *lcd)
+{
+ ili9320_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_shutdown);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("ILI9320 LCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
new file mode 100644
index 00000000000..e388eca7cac
--- /dev/null
+++ b/drivers/video/backlight/ili9320.h
@@ -0,0 +1,80 @@
+/* drivers/video/backlight/ili9320.h
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Holder for register and value pairs. */
+struct ili9320_reg {
+ unsigned short address;
+ unsigned short value;
+};
+
+struct ili9320;
+
+struct ili9320_client {
+ const char *name;
+ int (*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
+
+};
+/* Device attached via an SPI bus. */
+struct ili9320_spi {
+ struct spi_device *dev;
+ struct spi_message message;
+ struct spi_transfer xfer[2];
+
+ unsigned char id;
+ unsigned char buffer_addr[4];
+ unsigned char buffer_data[4];
+};
+
+/* ILI9320 device state. */
+struct ili9320 {
+ union {
+ struct ili9320_spi spi; /* SPI attachged device. */
+ } access; /* Register access method. */
+
+ struct device *dev;
+ struct lcd_device *lcd; /* LCD device we created. */
+ struct ili9320_client *client;
+ struct ili9320_platdata *platdata;
+
+ int power; /* current power state. */
+ int initialised;
+
+ unsigned short display1;
+ unsigned short power1;
+
+ int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val);
+};
+
+
+/* ILI9320 register access routines */
+
+extern int ili9320_write(struct ili9320 *ili,
+ unsigned int reg, unsigned int value);
+
+extern int ili9320_write_regs(struct ili9320 *ili,
+ struct ili9320_reg *values,
+ int nr_values);
+
+/* Device probe */
+
+extern int ili9320_probe_spi(struct spi_device *spi,
+ struct ili9320_client *cli);
+
+extern int ili9320_remove(struct ili9320 *lcd);
+extern void ili9320_shutdown(struct ili9320 *lcd);
+
+/* PM */
+
+extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state);
+extern int ili9320_resume(struct ili9320 *lcd);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 299fd318dd4..b15b2b84a6f 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -33,7 +33,7 @@ static int fb_notifier_callback(struct notifier_block *self,
ld = container_of(self, struct lcd_device, fb_notif);
mutex_lock(&ld->ops_lock);
if (ld->ops)
- if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+ if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
ld->ops->set_power(ld, *(int *)evdata->data);
mutex_unlock(&ld->ops_lock);
return 0;
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
new file mode 100644
index 00000000000..385cba40ea8
--- /dev/null
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -0,0 +1,116 @@
+/*
+ * Backlight Driver for Nvidia 8600 in Macbook Pro
+ *
+ * Copyright (c) Red Hat <mjg@redhat.com>
+ * Based on code from Pommed:
+ * Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
+ * Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
+ * Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This driver triggers SMIs which cause the firmware to change the
+ * backlight brightness. This is icky in many ways, but it's impractical to
+ * get at the firmware code in order to figure out what it's actually doing.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+
+static struct backlight_device *mbp_backlight_device;
+
+static struct dmi_system_id __initdata mbp_device_table[] = {
+ {
+ .ident = "3,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
+ },
+ },
+ {
+ .ident = "3,2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
+ },
+ },
+ {
+ .ident = "4,1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
+ },
+ },
+ { }
+};
+
+static int mbp_send_intensity(struct backlight_device *bd)
+{
+ int intensity = bd->props.brightness;
+
+ outb(0x04 | (intensity << 4), 0xb3);
+ outb(0xbf, 0xb2);
+
+ return 0;
+}
+
+static int mbp_get_intensity(struct backlight_device *bd)
+{
+ outb(0x03, 0xb3);
+ outb(0xbf, 0xb2);
+ return inb(0xb3) >> 4;
+}
+
+static struct backlight_ops mbp_ops = {
+ .get_brightness = mbp_get_intensity,
+ .update_status = mbp_send_intensity,
+};
+
+static int __init mbp_init(void)
+{
+ if (!dmi_check_system(mbp_device_table))
+ return -ENODEV;
+
+ if (!request_region(0xb2, 2, "Macbook Pro backlight"))
+ return -ENXIO;
+
+ mbp_backlight_device = backlight_device_register("mbp_backlight",
+ NULL, NULL,
+ &mbp_ops);
+ if (IS_ERR(mbp_backlight_device)) {
+ release_region(0xb2, 2);
+ return PTR_ERR(mbp_backlight_device);
+ }
+
+ mbp_backlight_device->props.max_brightness = 15;
+ mbp_backlight_device->props.brightness =
+ mbp_get_intensity(mbp_backlight_device);
+ backlight_update_status(mbp_backlight_device);
+
+ return 0;
+}
+
+static void __exit mbp_exit(void)
+{
+ backlight_device_unregister(mbp_backlight_device);
+
+ release_region(0xb2, 2);
+}
+
+module_init(mbp_init);
+module_exit(mbp_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
+MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
new file mode 100644
index 00000000000..72d44dbfce8
--- /dev/null
+++ b/drivers/video/backlight/platform_lcd.c
@@ -0,0 +1,172 @@
+/* drivers/video/backlight/platform_lcd.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <video/platform_lcd.h>
+
+struct platform_lcd {
+ struct device *us;
+ struct lcd_device *lcd;
+ struct plat_lcd_data *pdata;
+
+ unsigned int power;
+ unsigned int suspended : 1;
+};
+
+static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
+{
+ return lcd_get_data(lcd);
+}
+
+static int platform_lcd_get_power(struct lcd_device *lcd)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+
+ return plcd->power;
+}
+
+static int platform_lcd_set_power(struct lcd_device *lcd, int power)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+ int lcd_power = 1;
+
+ if (power == FB_BLANK_POWERDOWN || plcd->suspended)
+ lcd_power = 0;
+
+ plcd->pdata->set_power(plcd->pdata, lcd_power);
+ plcd->power = power;
+
+ return 0;
+}
+
+static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
+{
+ struct platform_lcd *plcd = to_our_lcd(lcd);
+ struct plat_lcd_data *pdata = plcd->pdata;
+
+ if (pdata->match_fb)
+ return pdata->match_fb(pdata, info);
+
+ return plcd->us->parent == info->device;
+}
+
+static struct lcd_ops platform_lcd_ops = {
+ .get_power = platform_lcd_get_power,
+ .set_power = platform_lcd_set_power,
+ .check_fb = platform_lcd_match,
+};
+
+static int __devinit platform_lcd_probe(struct platform_device *pdev)
+{
+ struct plat_lcd_data *pdata;
+ struct platform_lcd *plcd;
+ struct device *dev = &pdev->dev;
+ int err;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(dev, "no platform data supplied\n");
+ return -EINVAL;
+ }
+
+ plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+ if (!plcd) {
+ dev_err(dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ plcd->us = dev;
+ plcd->pdata = pdata;
+ plcd->lcd = lcd_device_register("platform-lcd", dev,
+ plcd, &platform_lcd_ops);
+ if (IS_ERR(plcd->lcd)) {
+ dev_err(dev, "cannot register lcd device\n");
+ err = PTR_ERR(plcd->lcd);
+ goto err_mem;
+ }
+
+ platform_set_drvdata(pdev, plcd);
+ return 0;
+
+ err_mem:
+ kfree(plcd);
+ return err;
+}
+
+static int __devexit platform_lcd_remove(struct platform_device *pdev)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ lcd_device_unregister(plcd->lcd);
+ kfree(plcd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ plcd->suspended = 1;
+ platform_lcd_set_power(plcd->lcd, plcd->power);
+
+ return 0;
+}
+
+static int platform_lcd_resume(struct platform_device *pdev)
+{
+ struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+ plcd->suspended = 0;
+ platform_lcd_set_power(plcd->lcd, plcd->power);
+
+ return 0;
+}
+#else
+#define platform_lcd_suspend NULL
+#define platform_lcd_resume NULL
+#endif
+
+static struct platform_driver platform_lcd_driver = {
+ .driver = {
+ .name = "platform-lcd",
+ .owner = THIS_MODULE,
+ },
+ .probe = platform_lcd_probe,
+ .remove = __devexit_p(platform_lcd_remove),
+ .suspend = platform_lcd_suspend,
+ .resume = platform_lcd_resume,
+};
+
+static int __init platform_lcd_init(void)
+{
+ return platform_driver_register(&platform_lcd_driver);
+}
+
+static void __exit platform_lcd_cleanup(void)
+{
+ platform_driver_unregister(&platform_lcd_driver);
+}
+
+module_init(platform_lcd_init);
+module_exit(platform_lcd_cleanup);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-lcd");
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
new file mode 100644
index 00000000000..593c7687d54
--- /dev/null
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -0,0 +1,284 @@
+/* drivers/video/backlight/vgg2432a4.c
+ *
+ * VGG2432A4 (ILI9320) LCD controller driver.
+ *
+ * Copyright 2007 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+/* Device initialisation sequences */
+
+static struct ili9320_reg vgg_init1[] = {
+ {
+ .address = ILI9320_POWER1,
+ .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
+ }, {
+ .address = ILI9320_POWER2,
+ .value = (ILI9320_POWER2_VC(7) |
+ ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
+ }, {
+ .address = ILI9320_POWER3,
+ .value = ILI9320_POWER3_VRH(0),
+ }, {
+ .address = ILI9320_POWER4,
+ .value = ILI9320_POWER4_VREOUT(0),
+ },
+};
+
+static struct ili9320_reg vgg_init2[] = {
+ {
+ .address = ILI9320_POWER1,
+ .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
+ ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
+ }, {
+ .address = ILI9320_POWER2,
+ .value = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
+ }
+};
+
+static struct ili9320_reg vgg_gamma[] = {
+ {
+ .address = ILI9320_GAMMA1,
+ .value = 0x0000,
+ }, {
+ .address = ILI9320_GAMMA2,
+ .value = 0x0505,
+ }, {
+ .address = ILI9320_GAMMA3,
+ .value = 0x0004,
+ }, {
+ .address = ILI9320_GAMMA4,
+ .value = 0x0006,
+ }, {
+ .address = ILI9320_GAMMA5,
+ .value = 0x0707,
+ }, {
+ .address = ILI9320_GAMMA6,
+ .value = 0x0105,
+ }, {
+ .address = ILI9320_GAMMA7,
+ .value = 0x0002,
+ }, {
+ .address = ILI9320_GAMMA8,
+ .value = 0x0707,
+ }, {
+ .address = ILI9320_GAMMA9,
+ .value = 0x0704,
+ }, {
+ .address = ILI9320_GAMMA10,
+ .value = 0x807,
+ }
+
+};
+
+static struct ili9320_reg vgg_init0[] = {
+ [0] = {
+ /* set direction and scan mode gate */
+ .address = ILI9320_DRIVER,
+ .value = ILI9320_DRIVER_SS,
+ }, {
+ .address = ILI9320_DRIVEWAVE,
+ .value = (ILI9320_DRIVEWAVE_MUSTSET |
+ ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
+ }, {
+ .address = ILI9320_ENTRYMODE,
+ .value = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
+ }, {
+ .address = ILI9320_RESIZING,
+ .value = 0x0,
+ },
+};
+
+
+static int vgg2432a4_lcd_init(struct ili9320 *lcd,
+ struct ili9320_platdata *cfg)
+{
+ unsigned int addr;
+ int ret;
+
+ /* Set VCore before anything else (VGG243237-6UFLWA) */
+ ret = ili9320_write(lcd, 0x00e5, 0x8000);
+ if (ret)
+ goto err_initial;
+
+ /* Start the oscillator up before we can do anything else. */
+ ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
+ if (ret)
+ goto err_initial;
+
+ /* must wait at-lesat 10ms after starting */
+ mdelay(15);
+
+ ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
+ if (ret != 0)
+ goto err_initial;
+
+ ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
+ ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
+ ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
+
+ ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
+ ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
+ ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL);
+
+ ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
+ if (ret != 0)
+ goto err_vgg;
+
+ mdelay(300);
+
+ ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
+ if (ret != 0)
+ goto err_vgg2;
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_POWER3, 0x13c);
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
+ ili9320_write(lcd, ILI9320_POWER7, 0x000e);
+
+ mdelay(100);
+
+ ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
+ ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
+
+ ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
+ if (ret != 0)
+ goto err_vgg3;
+
+ ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
+ ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
+ ili9320_write(lcd, ILI9320_VERT_START, 0x0);
+ ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
+
+ ili9320_write(lcd, ILI9320_DRIVER2,
+ ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
+
+ ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
+ ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
+
+ for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
+ addr++) {
+ ili9320_write(lcd, addr, 0x0);
+ }
+
+ ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
+ ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
+ ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
+ ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
+ ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
+ ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
+
+ lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
+ ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
+ 0x40);
+
+ ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+ return 0;
+
+ err_vgg3:
+ err_vgg2:
+ err_vgg:
+ err_initial:
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state)
+{
+ return ili9320_suspend(dev_get_drvdata(&spi->dev), state);
+}
+
+static int vgg2432a4_resume(struct spi_device *spi)
+{
+ return ili9320_resume(dev_get_drvdata(&spi->dev));
+}
+#else
+#define vgg2432a4_suspend NULL
+#define vgg2432a4_resume NULL
+#endif
+
+static struct ili9320_client vgg2432a4_client = {
+ .name = "VGG2432A4",
+ .init = vgg2432a4_lcd_init,
+};
+
+/* Device probe */
+
+static int __devinit vgg2432a4_probe(struct spi_device *spi)
+{
+ int ret;
+
+ ret = ili9320_probe_spi(spi, &vgg2432a4_client);
+ if (ret != 0) {
+ dev_err(&spi->dev, "failed to initialise ili9320\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit vgg2432a4_remove(struct spi_device *spi)
+{
+ return ili9320_remove(dev_get_drvdata(&spi->dev));
+}
+
+static void vgg2432a4_shutdown(struct spi_device *spi)
+{
+ ili9320_shutdown(dev_get_drvdata(&spi->dev));
+}
+
+static struct spi_driver vgg2432a4_driver = {
+ .driver = {
+ .name = "VGG2432A4",
+ .owner = THIS_MODULE,
+ },
+ .probe = vgg2432a4_probe,
+ .remove = __devexit_p(vgg2432a4_remove),
+ .shutdown = vgg2432a4_shutdown,
+ .suspend = vgg2432a4_suspend,
+ .resume = vgg2432a4_resume,
+};
+
+/* Device driver initialisation */
+
+static int __init vgg2432a4_init(void)
+{
+ return spi_register_driver(&vgg2432a4_driver);
+}
+
+static void __exit vgg2432a4_exit(void)
+{
+ spi_unregister_driver(&vgg2432a4_driver);
+}
+
+module_init(vgg2432a4_init);
+module_exit(vgg2432a4_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 49834a67a62..940467aed13 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
return 0;
}
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
{
if (!fi || (fi == &bfin_bf54x_fb))
return 1;
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 135d6dd7e67..7d1b819e501 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
return 0;
}
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
{
if (!fi || (fi == &bfin_t350mcqb_fb))
return 1;
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
new file mode 100644
index 00000000000..e15bb447440
--- /dev/null
+++ b/drivers/video/carminefb.c
@@ -0,0 +1,790 @@
+/*
+ * Frame buffer driver for the Carmine GPU.
+ *
+ * The driver configures the GPU as follows
+ * - FB0 is display 0 with unique memory area
+ * - FB1 is display 1 with unique memory area
+ * - both display use 32 bit colors
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#include "carminefb.h"
+#include "carminefb_regs.h"
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error "The endianness of the target host has not been defined."
+#endif
+
+/*
+ * The initial video mode can be supplied via two different ways:
+ * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
+ * - as an integer that picks the video mode from carmine_modedb[] (module
+ * option fb_mode)
+ *
+ * If nothing is used than the initial video mode will be the
+ * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
+ */
+#define CARMINEFB_DEFAULT_VIDEO_MODE 1
+
+static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+module_param(fb_mode, uint, 444);
+MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
+
+static char *fb_mode_str;
+module_param(fb_mode_str, charp, 444);
+MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
+
+/*
+ * Carminefb displays:
+ * 0b000 None
+ * 0b001 Display 0
+ * 0b010 Display 1
+ */
+static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
+module_param(fb_displays, int, 444);
+MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
+
+struct carmine_hw {
+ void __iomem *v_regs;
+ void __iomem *screen_mem;
+ struct fb_info *fb[MAX_DISPLAY];
+};
+
+struct carmine_resolution {
+ u32 htp;
+ u32 hsp;
+ u32 hsw;
+ u32 hdp;
+ u32 vtr;
+ u32 vsp;
+ u32 vsw;
+ u32 vdp;
+ u32 disp_mode;
+};
+
+struct carmine_fb {
+ void __iomem *display_reg;
+ void __iomem *screen_base;
+ u32 smem_offset;
+ u32 cur_mode;
+ u32 new_mode;
+ struct carmine_resolution *res;
+ u32 pseudo_palette[16];
+};
+
+static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
+ .id = "Carmine",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static const struct fb_videomode carmine_modedb[] = {
+ {
+ .name = "640x480",
+ .xres = 640,
+ .yres = 480,
+ }, {
+ .name = "800x600",
+ .xres = 800,
+ .yres = 600,
+ },
+};
+
+static struct carmine_resolution car_modes[] = {
+ {
+ /* 640x480 */
+ .htp = 800,
+ .hsp = 672,
+ .hsw = 96,
+ .hdp = 640,
+ .vtr = 525,
+ .vsp = 490,
+ .vsw = 2,
+ .vdp = 480,
+ .disp_mode = 0x1400,
+ },
+ {
+ /* 800x600 */
+ .htp = 1060,
+ .hsp = 864,
+ .hsw = 72,
+ .hdp = 800,
+ .vtr = 628,
+ .vsp = 601,
+ .vsw = 2,
+ .vdp = 600,
+ .disp_mode = 0x0d00,
+ }
+};
+
+static int carmine_find_mode(const struct fb_var_screeninfo *var)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(car_modes); i++)
+ if (car_modes[i].hdp == var->xres &&
+ car_modes[i].vdp == var->yres)
+ return i;
+ return -EINVAL;
+}
+
+static void c_set_disp_reg(const struct carmine_fb *par,
+ u32 offset, u32 val)
+{
+ writel(val, par->display_reg + offset);
+}
+
+static u32 c_get_disp_reg(const struct carmine_fb *par,
+ u32 offset)
+{
+ return readl(par->display_reg + offset);
+}
+
+static void c_set_hw_reg(const struct carmine_hw *hw,
+ u32 offset, u32 val)
+{
+ writel(val, hw->v_regs + offset);
+}
+
+static u32 c_get_hw_reg(const struct carmine_hw *hw,
+ u32 offset)
+{
+ return readl(hw->v_regs + offset);
+}
+
+static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ if (regno >= 16)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ transp >>= 8;
+
+ ((u32 *)info->pseudo_palette)[regno] = be32_to_cpu(transp << 24 |
+ red << 0 | green << 8 | blue << 16);
+ return 0;
+}
+
+static int carmine_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int ret;
+
+ ret = carmine_find_mode(var);
+ if (ret < 0)
+ return ret;
+
+ if (var->grayscale || var->rotate || var->nonstd)
+ return -EINVAL;
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ var->bits_per_pixel = 32;
+
+#ifdef __BIG_ENDIAN
+ var->transp.offset = 24;
+ var->red.offset = 0;
+ var->green.offset = 8;
+ var->blue.offset = 16;
+#else
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+#endif
+
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ var->transp.length = 8;
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ return 0;
+}
+
+static void carmine_init_display_param(struct carmine_fb *par)
+{
+ u32 width;
+ u32 height;
+ u32 param;
+ u32 window_size;
+ u32 soffset = par->smem_offset;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
+ CARMINE_CURSOR0_PRIORITY_MASK |
+ CARMINE_CURSOR1_PRIORITY_MASK |
+ CARMINE_CURSOR_CUTZ_MASK);
+
+ /* Set default cursor position */
+ c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
+
+ /* Set default display mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
+ CARMINE_EXT_CMODE_DIRECT24_RGBA);
+
+ /* Set default frame size to layer mode register */
+ width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
+ width = width << CARMINE_DISP_WIDTH_SHIFT;
+
+ height = par->res->vdp - 1;
+ param = width | height;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
+
+ /* Set default pos and size */
+ window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
+ window_size |= par->res->hdp;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
+
+ /* Set default origin address */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
+
+ /* Set default display address */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
+
+ /* Set default display position */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
+
+ /* Set default blend mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
+
+ /* default transparency mode */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
+
+ /* Set default read skip parameter */
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
+ c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
+}
+
+static void set_display_parameters(struct carmine_fb *par)
+{
+ u32 mode;
+ u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
+
+ /*
+ * display timing. Parameters are decreased by one because hardware
+ * spec is 0 to (n - 1)
+ * */
+ hdp = par->res->hdp - 1;
+ vdp = par->res->vdp - 1;
+ htp = par->res->htp - 1;
+ hsp = par->res->hsp - 1;
+ hsw = par->res->hsw - 1;
+ vtr = par->res->vtr - 1;
+ vsp = par->res->vsp - 1;
+ vsw = par->res->vsw - 1;
+
+ c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
+ htp << CARMINE_DISP_HTP_SHIFT);
+ c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
+ (hdp << CARMINE_DISP_HDB_SHIFT) | hdp);
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
+ (vsw << CARMINE_DISP_VSW_SHIFT) |
+ (hsw << CARMINE_DISP_HSW_SHIFT) |
+ (hsp));
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
+ vtr << CARMINE_DISP_VTR_SHIFT);
+ c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
+ (vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
+
+ /* clock */
+ mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
+ mode = (mode & ~CARMINE_DISP_DCM_MASK) |
+ (par->res->disp_mode & CARMINE_DISP_DCM_MASK);
+ /* enable video output and layer 0 */
+ mode |= CARMINE_DEN | CARMINE_L0E;
+ c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
+}
+
+static int carmine_set_par(struct fb_info *info)
+{
+ struct carmine_fb *par = info->par;
+ int ret;
+
+ ret = carmine_find_mode(&info->var);
+ if (ret < 0)
+ return ret;
+
+ par->new_mode = ret;
+ if (par->cur_mode != par->new_mode) {
+
+ par->cur_mode = par->new_mode;
+ par->res = &car_modes[par->new_mode];
+
+ carmine_init_display_param(par);
+ set_display_parameters(par);
+ }
+
+ info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
+ return 0;
+}
+
+static int init_hardware(struct carmine_hw *hw)
+{
+ u32 flags;
+ u32 loops;
+ u32 ret;
+
+ /* Initalize Carmine */
+ /* Sets internal clock */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
+ CARMINE_DFLT_IP_CLOCK_ENABLE);
+
+ /* Video signal output is turned off */
+ c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+
+ /* Software reset */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
+
+ /* I/O mode settings */
+ flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
+ CARMINE_DFLT_IP_DCTL_IO_CONT0;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
+ flags);
+
+ /* DRAM initial sequence */
+ flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
+ CARMINE_DFLT_IP_DCTL_EMODE;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
+ CARMINE_DFLT_IP_DCTL_SET_TIME2;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
+ CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
+ flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+ CARMINE_DFLT_IP_DCTL_STATES;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+ flags);
+
+ /* Executes DLL reset */
+ if (CARMINE_DCTL_DLL_RESET) {
+ for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
+
+ ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
+ CARMINE_DCTL_REG_RSV0_STATES);
+ ret &= CARMINE_DCTL_REG_STATES_MASK;
+ if (!ret)
+ break;
+
+ mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
+ }
+
+ if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
+ printk(KERN_ERR "DRAM init failed\n");
+ return -EIO;
+ }
+ }
+
+ flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
+ CARMINE_DFLT_IP_DCTL_ADD;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
+
+ flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
+ CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
+ c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
+ flags);
+
+ /* Initialize the write back register */
+ c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
+ CARMINE_WB_REG_WBM_DEFAULT);
+
+ /* Initialize the Kottos registers */
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
+
+ /* Set DC offsets */
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
+ c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
+ return 0;
+}
+
+static struct fb_ops carminefb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+
+ .fb_check_var = carmine_check_var,
+ .fb_set_par = carmine_set_par,
+ .fb_setcolreg = carmine_setcolreg,
+};
+
+static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+ int smem_offset, struct device *device, struct fb_info **rinfo)
+{
+ int ret;
+ struct fb_info *info;
+ struct carmine_fb *par;
+
+ info = framebuffer_alloc(sizeof *par, device);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->display_reg = regs;
+ par->smem_offset = smem_offset;
+
+ info->screen_base = smem_base + smem_offset;
+ info->screen_size = CARMINE_DISPLAY_MEM;
+ info->fbops = &carminefb_ops;
+
+ info->fix = carminefb_fix;
+ info->pseudo_palette = par->pseudo_palette;
+ info->flags = FBINFO_DEFAULT;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 1);
+ if (ret < 0)
+ goto err_free_fb;
+
+ if (fb_mode > ARRAY_SIZE(carmine_modedb))
+ fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
+
+ par->cur_mode = par->new_mode = ~0;
+
+ ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
+ ARRAY_SIZE(carmine_modedb),
+ &carmine_modedb[fb_mode], 32);
+ if (!ret || ret == 4) {
+ ret = -EINVAL;
+ goto err_dealloc_cmap;
+ }
+
+ fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
+ &info->modelist);
+
+ ret = register_framebuffer(info);
+ if (ret < 0)
+ goto err_dealloc_cmap;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+
+ *rinfo = info;
+ return 0;
+
+err_dealloc_cmap:
+ fb_dealloc_cmap(&info->cmap);
+err_free_fb:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void cleanup_fb_device(struct fb_info *info)
+{
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(info);
+ }
+}
+
+static int __devinit carminefb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct carmine_hw *hw;
+ struct device *device = &dev->dev;
+ struct fb_info *info;
+ int ret;
+
+ ret = pci_enable_device(dev);
+ if (ret)
+ return ret;
+
+ ret = -ENOMEM;
+ hw = kzalloc(sizeof *hw, GFP_KERNEL);
+ if (!hw)
+ goto err_enable_pci;
+
+ carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
+ carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
+
+ if (!request_mem_region(carminefb_fix.mmio_start,
+ carminefb_fix.mmio_len,
+ "carminefb regbase")) {
+ printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
+ ret = -EBUSY;
+ goto err_free_hw;
+ }
+ hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
+ carminefb_fix.mmio_len);
+ if (!hw->v_regs) {
+ printk(KERN_ERR "carminefb: Can't remap %s register.\n",
+ carminefb_fix.id);
+ goto err_free_reg_mmio;
+ }
+
+ carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
+ carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
+
+ /* The memory area tends to be very large (256 MiB). Remap only what
+ * is required for that largest resolution to avoid remaps at run
+ * time
+ */
+ if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
+ carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
+
+ else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
+ printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
+ "are required.", carminefb_fix.smem_len,
+ CARMINE_TOTAL_DIPLAY_MEM);
+ goto err_free_reg_mmio;
+ }
+
+ if (!request_mem_region(carminefb_fix.smem_start,
+ carminefb_fix.smem_len, "carminefb smem")) {
+ printk(KERN_ERR "carminefb: Can't reserve smem.\n");
+ goto err_unmap_vregs;
+ }
+
+ hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
+ carminefb_fix.smem_len);
+ if (!hw->screen_mem) {
+ printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
+ release_mem_region(carminefb_fix.smem_start,
+ carminefb_fix.smem_len);
+ goto err_reg_smem;
+ }
+
+ ret = init_hardware(hw);
+ if (ret)
+ goto err_unmap_screen;
+
+ info = NULL;
+ if (fb_displays & CARMINE_USE_DISPLAY0) {
+ ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
+ hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
+ device, &info);
+ if (ret)
+ goto err_deinit_hw;
+ }
+
+ hw->fb[0] = info;
+
+ info = NULL;
+ if (fb_displays & CARMINE_USE_DISPLAY1) {
+ ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
+ hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
+ device, &info);
+ if (ret)
+ goto err_cleanup_fb0;
+ }
+
+ hw->fb[1] = info;
+ info = NULL;
+
+ pci_set_drvdata(dev, hw);
+ return 0;
+
+err_cleanup_fb0:
+ cleanup_fb_device(hw->fb[0]);
+err_deinit_hw:
+ /* disable clock, etc */
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+err_unmap_screen:
+ iounmap(hw->screen_mem);
+err_reg_smem:
+ release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_unmap_vregs:
+ iounmap(hw->v_regs);
+err_free_reg_mmio:
+ release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
+err_free_hw:
+ kfree(hw);
+err_enable_pci:
+ pci_disable_device(dev);
+ return ret;
+}
+
+static void __devexit carminefb_remove(struct pci_dev *dev)
+{
+ struct carmine_hw *hw = pci_get_drvdata(dev);
+ struct fb_fix_screeninfo fix;
+ int i;
+
+ /* in case we use only fb1 and not fb1 */
+ if (hw->fb[0])
+ fix = hw->fb[0]->fix;
+ else
+ fix = hw->fb[1]->fix;
+
+ /* deactivate display(s) and switch clocks */
+ c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
+ c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
+
+ for (i = 0; i < MAX_DISPLAY; i++)
+ cleanup_fb_device(hw->fb[i]);
+
+ iounmap(hw->screen_mem);
+ release_mem_region(fix.smem_start, fix.smem_len);
+ iounmap(hw->v_regs);
+ release_mem_region(fix.mmio_start, fix.mmio_len);
+
+ pci_set_drvdata(dev, NULL);
+ pci_disable_device(dev);
+ kfree(hw);
+}
+
+#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
+static struct pci_device_id carmine_devices[] __devinitdata = {
+{
+ PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, carmine_devices);
+
+static struct pci_driver carmine_pci_driver = {
+ .name = "carminefb",
+ .id_table = carmine_devices,
+ .probe = carminefb_probe,
+ .remove = __devexit_p(carminefb_remove),
+};
+
+static int __init carminefb_init(void)
+{
+ if (!(fb_displays &
+ (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
+ printk(KERN_ERR "If you disable both displays than you don't "
+ "need the driver at all\n");
+ return -EINVAL;
+ }
+ return pci_register_driver(&carmine_pci_driver);
+}
+module_init(carminefb_init);
+
+static void __exit carminefb_cleanup(void)
+{
+ pci_unregister_driver(&carmine_pci_driver);
+}
+module_exit(carminefb_cleanup);
+
+MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h
new file mode 100644
index 00000000000..05306de0c6b
--- /dev/null
+++ b/drivers/video/carminefb.h
@@ -0,0 +1,64 @@
+#ifndef CARMINE_CARMINE_H
+#define CARMINE_CARMINE_H
+
+#define CARMINE_MEMORY_BAR 2
+#define CARMINE_CONFIG_BAR 3
+
+#define MAX_DISPLAY 2
+#define CARMINE_DISPLAY_MEM (800 * 600 * 4)
+#define CARMINE_TOTAL_DIPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY)
+
+#define CARMINE_USE_DISPLAY0 (1 << 0)
+#define CARMINE_USE_DISPLAY1 (1 << 1)
+
+/*
+ * This values work on the eval card. Custom boards may use different timings,
+ * here an example :)
+ */
+
+/* DRAM initialization values */
+#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD (0x05c3)
+#define CARMINE_DFLT_IP_DCTL_MODE (0x0121)
+#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x4749)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x2a22)
+#define CARMINE_DFLT_IP_DCTL_REFRESH (0x0042)
+#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x6646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x0055)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0021)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
+#define CARMINE_DCTL_DLL_RESET (1)
+#endif
+
+#ifdef CONFIG_CARMINE_DRAM_CUSTOM
+
+#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
+#define CARMINE_DFLT_IP_DCTL_ADD (0x03b2)
+#define CARMINE_DFLT_IP_DCTL_MODE (0x0161)
+#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x2628)
+#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x1a09)
+#define CARMINE_DFLT_IP_DCTL_REFRESH (0x00fe)
+#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
+#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
+#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
+#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
+#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x0646)
+#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x55aa)
+#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0061)
+#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
+#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
+#define CARMINE_DCTL_DLL_RESET (1)
+#endif
+
+#endif
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h
new file mode 100644
index 00000000000..045215600b7
--- /dev/null
+++ b/drivers/video/carminefb_regs.h
@@ -0,0 +1,159 @@
+#ifndef _CARMINEFB_REGS_H
+#define _CARMINEFB_REGS_H
+
+#define CARMINE_OVERLAY_EXT_MODE (0x00000002)
+#define CARMINE_GRAPH_REG (0x00000000)
+#define CARMINE_DISP0_REG (0x00100000)
+#define CARMINE_DISP1_REG (0x00140000)
+#define CARMINE_WB_REG (0x00180000)
+#define CARMINE_DCTL_REG (0x00300000)
+#define CARMINE_CTL_REG (0x00400000)
+#define CARMINE_WINDOW_MODE (0x00000001)
+#define CARMINE_EXTEND_MODE (CARMINE_WINDOW_MODE | \
+ CARMINE_OVERLAY_EXT_MODE)
+#define CARMINE_L0E (1 << 16)
+#define CARMINE_L2E (1 << 18)
+#define CARMINE_DEN (1 << 31)
+
+#define CARMINE_EXT_CMODE_DIRECT24_RGBA (0xC0000000)
+#define CARMINE_DCTL_REG_MODE_ADD (0x00)
+#define CARMINE_DCTL_REG_SETTIME1_EMODE (0x04)
+#define CARMINE_DCTL_REG_REFRESH_SETTIME2 (0x08)
+#define CARMINE_DCTL_REG_RSV0_STATES (0x0C)
+#define CARMINE_DCTL_REG_RSV2_RSV1 (0x10)
+#define CARMINE_DCTL_REG_DDRIF2_DDRIF1 (0x14)
+#define CARMINE_DCTL_REG_IOCONT1_IOCONT0 (0x24)
+#define CARMINE_DCTL_REG_STATES_MASK (0x000F)
+#define CARMINE_DCTL_INIT_WAIT_INTERVAL (1)
+#define CARMINE_DCTL_INIT_WAIT_LIMIT (5000)
+#define CARMINE_WB_REG_WBM_DEFAULT (0x0001c020)
+#define CARMINE_DISP_REG_L0RM (0x1880)
+#define CARMINE_DISP_REG_L0PX (0x1884)
+#define CARMINE_DISP_REG_L0PY (0x1888)
+#define CARMINE_DISP_REG_L2RM (0x18A0)
+#define CARMINE_DISP_REG_L2PX (0x18A4)
+#define CARMINE_DISP_REG_L2PY (0x18A8)
+#define CARMINE_DISP_REG_L3RM (0x18B0)
+#define CARMINE_DISP_REG_L3PX (0x18B4)
+#define CARMINE_DISP_REG_L3PY (0x18B8)
+#define CARMINE_DISP_REG_L4RM (0x18C0)
+#define CARMINE_DISP_REG_L4PX (0x18C4)
+#define CARMINE_DISP_REG_L4PY (0x18C8)
+#define CARMINE_DISP_REG_L5RM (0x18D0)
+#define CARMINE_DISP_REG_L5PX (0x18D4)
+#define CARMINE_DISP_REG_L5PY (0x18D8)
+#define CARMINE_DISP_REG_L6RM (0x1924)
+#define CARMINE_DISP_REG_L6PX (0x1928)
+#define CARMINE_DISP_REG_L6PY (0x192C)
+#define CARMINE_DISP_REG_L7RM (0x1964)
+#define CARMINE_DISP_REG_L7PX (0x1968)
+#define CARMINE_DISP_REG_L7PY (0x196C)
+#define CARMINE_WB_REG_WBM (0x0004)
+#define CARMINE_DISP_HTP_SHIFT (16)
+#define CARMINE_DISP_HDB_SHIFT (16)
+#define CARMINE_DISP_HSW_SHIFT (16)
+#define CARMINE_DISP_VSW_SHIFT (24)
+#define CARMINE_DISP_VTR_SHIFT (16)
+#define CARMINE_DISP_VDP_SHIFT (16)
+#define CARMINE_CURSOR_CUTZ_MASK (0x00000100)
+#define CARMINE_CURSOR0_PRIORITY_MASK (0x00010000)
+#define CARMINE_CURSOR1_PRIORITY_MASK (0x00020000)
+#define CARMINE_DISP_WIDTH_SHIFT (16)
+#define CARMINE_DISP_WIN_H_SHIFT (16)
+#define CARMINE_DISP_REG_H_TOTAL (0x0004)
+#define CARMINE_DISP_REG_H_PERIOD (0x0008)
+#define CARMINE_DISP_REG_V_H_W_H_POS (0x000C)
+#define CARMINE_DISP_REG_V_TOTAL (0x0010)
+#define CARMINE_DISP_REG_V_PERIOD_POS (0x0014)
+#define CARMINE_DISP_REG_L0_MODE_W_H (0x0020)
+#define CARMINE_DISP_REG_L0_ORG_ADR (0x0024)
+#define CARMINE_DISP_REG_L0_DISP_ADR (0x0028)
+#define CARMINE_DISP_REG_L0_DISP_POS (0x002C)
+#define CARMINE_DISP_REG_L1_WIDTH (0x0030)
+#define CARMINE_DISP_REG_L1_ORG_ADR (0x0034)
+#define CARMINE_DISP_REG_L2_MODE_W_H (0x0040)
+#define CARMINE_DISP_REG_L2_ORG_ADR1 (0x0044)
+#define CARMINE_DISP_REG_L2_DISP_ADR1 (0x0048)
+#define CARMINE_DISP_REG_L2_DISP_POS (0x0054)
+#define CARMINE_DISP_REG_L3_MODE_W_H (0x0058)
+#define CARMINE_DISP_REG_L3_ORG_ADR1 (0x005C)
+#define CARMINE_DISP_REG_L3_DISP_ADR1 (0x0060)
+#define CARMINE_DISP_REG_L3_DISP_POS (0x006C)
+#define CARMINE_DISP_REG_L4_MODE_W_H (0x0070)
+#define CARMINE_DISP_REG_L4_ORG_ADR1 (0x0074)
+#define CARMINE_DISP_REG_L4_DISP_ADR1 (0x0078)
+#define CARMINE_DISP_REG_L4_DISP_POS (0x0084)
+#define CARMINE_DISP_REG_L5_MODE_W_H (0x0088)
+#define CARMINE_DISP_REG_L5_ORG_ADR1 (0x008C)
+#define CARMINE_DISP_REG_L5_DISP_ADR1 (0x0090)
+#define CARMINE_DISP_REG_L5_DISP_POS (0x009C)
+#define CARMINE_DISP_REG_CURSOR_MODE (0x00A0)
+#define CARMINE_DISP_REG_CUR1_POS (0x00A8)
+#define CARMINE_DISP_REG_CUR2_POS (0x00B0)
+#define CARMINE_DISP_REG_C_TRANS (0x00BC)
+#define CARMINE_DISP_REG_MLMR_TRANS (0x00C0)
+#define CARMINE_DISP_REG_L0_EXT_MODE (0x0110)
+#define CARMINE_DISP_REG_L0_WIN_POS (0x0114)
+#define CARMINE_DISP_REG_L0_WIN_SIZE (0x0118)
+#define CARMINE_DISP_REG_L1_EXT_MODE (0x0120)
+#define CARMINE_DISP_REG_L1_WIN_POS (0x0124)
+#define CARMINE_DISP_REG_L1_WIN_SIZE (0x0128)
+#define CARMINE_DISP_REG_L2_EXT_MODE (0x0130)
+#define CARMINE_DISP_REG_L2_WIN_POS (0x0134)
+#define CARMINE_DISP_REG_L2_WIN_SIZE (0x0138)
+#define CARMINE_DISP_REG_L3_EXT_MODE (0x0140)
+#define CARMINE_DISP_REG_L3_WIN_POS (0x0144)
+#define CARMINE_DISP_REG_L3_WIN_SIZE (0x0148)
+#define CARMINE_DISP_REG_L4_EXT_MODE (0x0150)
+#define CARMINE_DISP_REG_L4_WIN_POS (0x0154)
+#define CARMINE_DISP_REG_L4_WIN_SIZE (0x0158)
+#define CARMINE_DISP_REG_L5_EXT_MODE (0x0160)
+#define CARMINE_DISP_REG_L5_WIN_POS (0x0164)
+#define CARMINE_DISP_REG_L5_WIN_SIZE (0x0168)
+#define CARMINE_DISP_REG_L6_EXT_MODE (0x1918)
+#define CARMINE_DISP_REG_L6_WIN_POS (0x191c)
+#define CARMINE_DISP_REG_L6_WIN_SIZE (0x1920)
+#define CARMINE_DISP_REG_L7_EXT_MODE (0x1958)
+#define CARMINE_DISP_REG_L7_WIN_POS (0x195c)
+#define CARMINE_DISP_REG_L7_WIN_SIZE (0x1960)
+#define CARMINE_DISP_REG_BLEND_MODE_L0 (0x00B4)
+#define CARMINE_DISP_REG_BLEND_MODE_L1 (0x0188)
+#define CARMINE_DISP_REG_BLEND_MODE_L2 (0x018C)
+#define CARMINE_DISP_REG_BLEND_MODE_L3 (0x0190)
+#define CARMINE_DISP_REG_BLEND_MODE_L4 (0x0194)
+#define CARMINE_DISP_REG_BLEND_MODE_L5 (0x0198)
+#define CARMINE_DISP_REG_BLEND_MODE_L6 (0x1990)
+#define CARMINE_DISP_REG_BLEND_MODE_L7 (0x1994)
+#define CARMINE_DISP_REG_L0_TRANS (0x01A0)
+#define CARMINE_DISP_REG_L1_TRANS (0x01A4)
+#define CARMINE_DISP_REG_L2_TRANS (0x01A8)
+#define CARMINE_DISP_REG_L3_TRANS (0x01AC)
+#define CARMINE_DISP_REG_L4_TRANS (0x01B0)
+#define CARMINE_DISP_REG_L5_TRANS (0x01B4)
+#define CARMINE_DISP_REG_L6_TRANS (0x1998)
+#define CARMINE_DISP_REG_L7_TRANS (0x199c)
+#define CARMINE_EXTEND_MODE_MASK (0x00000003)
+#define CARMINE_DISP_DCM_MASK (0x0000FFFF)
+#define CARMINE_DISP_REG_DCM1 (0x0100)
+#define CARMINE_DISP_WIDTH_UNIT (64)
+#define CARMINE_DISP_REG_L6_MODE_W_H (0x1900)
+#define CARMINE_DISP_REG_L6_ORG_ADR1 (0x1904)
+#define CARMINE_DISP_REG_L6_DISP_ADR0 (0x1908)
+#define CARMINE_DISP_REG_L6_DISP_POS (0x1914)
+#define CARMINE_DISP_REG_L7_MODE_W_H (0x1940)
+#define CARMINE_DISP_REG_L7_ORG_ADR1 (0x1944)
+#define CARMINE_DISP_REG_L7_DISP_ADR0 (0x1948)
+#define CARMINE_DISP_REG_L7_DISP_POS (0x1954)
+#define CARMINE_CTL_REG_CLOCK_ENABLE (0x000C)
+#define CARMINE_CTL_REG_SOFTWARE_RESET (0x0010)
+#define CARMINE_CTL_REG_IST_MASK_ALL (0x07FFFFFF)
+#define CARMINE_GRAPH_REG_VRINTM (0x00028064)
+#define CARMINE_GRAPH_REG_VRERRM (0x0002806C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PX (0x0004005C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_PY (0x00040060)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LX (0x00040064)
+#define CARMINE_GRAPH_REG_DC_OFFSET_LY (0x00040068)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TX (0x0004006C)
+#define CARMINE_GRAPH_REG_DC_OFFSET_TY (0x00040070)
+
+#endif
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
new file mode 100644
index 00000000000..7bad24ed04e
--- /dev/null
+++ b/drivers/video/cobalt_lcdfb.c
@@ -0,0 +1,371 @@
+/*
+ * Cobalt server LCD frame buffer driver.
+ *
+ * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+
+/*
+ * Cursor position address
+ * \X 0 1 2 ... 14 15
+ * Y+----+----+----+---+----+----+
+ * 0|0x00|0x01|0x02|...|0x0e|0x0f|
+ * +----+----+----+---+----+----+
+ * 1|0x40|0x41|0x42|...|0x4e|0x4f|
+ * +----+----+----+---+----+----+
+ */
+#define LCD_DATA_REG_OFFSET 0x10
+#define LCD_XRES_MAX 16
+#define LCD_YRES_MAX 2
+#define LCD_CHARS_MAX 32
+
+#define LCD_CLEAR 0x01
+#define LCD_CURSOR_MOVE_HOME 0x02
+#define LCD_RESET 0x06
+#define LCD_OFF 0x08
+#define LCD_CURSOR_OFF 0x0c
+#define LCD_CURSOR_BLINK_OFF 0x0e
+#define LCD_CURSOR_ON 0x0f
+#define LCD_ON LCD_CURSOR_ON
+#define LCD_CURSOR_MOVE_LEFT 0x10
+#define LCD_CURSOR_MOVE_RIGHT 0x14
+#define LCD_DISPLAY_LEFT 0x18
+#define LCD_DISPLAY_RIGHT 0x1c
+#define LCD_PRERESET 0x3f /* execute 4 times continuously */
+#define LCD_BUSY 0x80
+
+#define LCD_GRAPHIC_MODE 0x40
+#define LCD_TEXT_MODE 0x80
+#define LCD_CUR_POS_MASK 0x7f
+
+#define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK)
+#define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE)
+
+static inline void lcd_write_control(struct fb_info *info, u8 control)
+{
+ writel((u32)control << 24, info->screen_base);
+}
+
+static inline u8 lcd_read_control(struct fb_info *info)
+{
+ return readl(info->screen_base) >> 24;
+}
+
+static inline void lcd_write_data(struct fb_info *info, u8 data)
+{
+ writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
+}
+
+static inline u8 lcd_read_data(struct fb_info *info)
+{
+ return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
+}
+
+static int lcd_busy_wait(struct fb_info *info)
+{
+ u8 val = 0;
+ int timeout = 10, retval = 0;
+
+ do {
+ val = lcd_read_control(info);
+ val &= LCD_BUSY;
+ if (val != LCD_BUSY)
+ break;
+
+ if (msleep_interruptible(1))
+ return -EINTR;
+
+ timeout--;
+ } while (timeout);
+
+ if (val == LCD_BUSY)
+ retval = -EBUSY;
+
+ return retval;
+}
+
+static void lcd_clear(struct fb_info *info)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ udelay(150);
+
+ lcd_write_control(info, LCD_PRERESET);
+ }
+
+ udelay(150);
+
+ lcd_write_control(info, LCD_CLEAR);
+
+ udelay(150);
+
+ lcd_write_control(info, LCD_RESET);
+}
+
+static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = {
+ .id = "cobalt-lcd",
+ .type = FB_TYPE_TEXT,
+ .type_aux = FB_AUX_TEXT_MDA,
+ .visual = FB_VISUAL_MONO01,
+ .line_length = LCD_XRES_MAX,
+ .accel = FB_ACCEL_NONE,
+};
+
+static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char src[LCD_CHARS_MAX];
+ unsigned long pos;
+ int len, retval = 0;
+
+ pos = *ppos;
+ if (pos >= LCD_CHARS_MAX || count == 0)
+ return 0;
+
+ if (count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX;
+
+ if (pos + count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX - pos;
+
+ for (len = 0; len < count; len++) {
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_control(info, LCD_TEXT_POS(pos));
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ src[len] = lcd_read_data(info);
+ if (pos == 0x0f)
+ pos = 0x40;
+ else
+ pos++;
+ }
+
+ if (retval < 0 && signal_pending(current))
+ return -ERESTARTSYS;
+
+ if (copy_to_user(buf, src, len))
+ return -EFAULT;
+
+ *ppos += len;
+
+ return len;
+}
+
+static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char dst[LCD_CHARS_MAX];
+ unsigned long pos;
+ int len, retval = 0;
+
+ pos = *ppos;
+ if (pos >= LCD_CHARS_MAX || count == 0)
+ return 0;
+
+ if (count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX;
+
+ if (pos + count > LCD_CHARS_MAX)
+ count = LCD_CHARS_MAX - pos;
+
+ if (copy_from_user(dst, buf, count))
+ return -EFAULT;
+
+ for (len = 0; len < count; len++) {
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_control(info, LCD_TEXT_POS(pos));
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ break;
+
+ lcd_write_data(info, dst[len]);
+ if (pos == 0x0f)
+ pos = 0x40;
+ else
+ pos++;
+ }
+
+ if (retval < 0 && signal_pending(current))
+ return -ERESTARTSYS;
+
+ *ppos += len;
+
+ return len;
+}
+
+static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
+{
+ int retval;
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ lcd_write_control(info, LCD_ON);
+ break;
+ default:
+ lcd_write_control(info, LCD_OFF);
+ break;
+ }
+
+ return 0;
+}
+
+static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ u32 x, y;
+ int retval;
+
+ switch (cursor->set) {
+ case FB_CUR_SETPOS:
+ x = cursor->image.dx;
+ y = cursor->image.dy;
+ if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
+ return -EINVAL;
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ lcd_write_control(info,
+ LCD_TEXT_POS(info->fix.line_length * y + x));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ retval = lcd_busy_wait(info);
+ if (retval < 0)
+ return retval;
+
+ if (cursor->enable)
+ lcd_write_control(info, LCD_CURSOR_ON);
+ else
+ lcd_write_control(info, LCD_CURSOR_OFF);
+
+ return 0;
+}
+
+static struct fb_ops cobalt_lcd_fbops = {
+ .owner = THIS_MODULE,
+ .fb_read = cobalt_lcdfb_read,
+ .fb_write = cobalt_lcdfb_write,
+ .fb_blank = cobalt_lcdfb_blank,
+ .fb_cursor = cobalt_lcdfb_cursor,
+};
+
+static int __init cobalt_lcdfb_probe(struct platform_device *dev)
+{
+ struct fb_info *info;
+ struct resource *res;
+ int retval;
+
+ info = framebuffer_alloc(0, &dev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ framebuffer_release(info);
+ return -EBUSY;
+ }
+
+ info->screen_size = res->end - res->start + 1;
+ info->screen_base = ioremap(res->start, info->screen_size);
+ info->fbops = &cobalt_lcd_fbops;
+ info->fix = cobalt_lcdfb_fix;
+ info->fix.smem_start = res->start;
+ info->fix.smem_len = info->screen_size;
+ info->pseudo_palette = NULL;
+ info->par = NULL;
+ info->flags = FBINFO_DEFAULT;
+
+ retval = register_framebuffer(info);
+ if (retval < 0) {
+ iounmap(info->screen_base);
+ framebuffer_release(info);
+ return retval;
+ }
+
+ platform_set_drvdata(dev, info);
+
+ lcd_clear(info);
+
+ printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n",
+ info->node);
+
+ return 0;
+}
+
+static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
+{
+ struct fb_info *info;
+
+ info = platform_get_drvdata(dev);
+ if (info) {
+ iounmap(info->screen_base);
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
+
+static struct platform_driver cobalt_lcdfb_driver = {
+ .probe = cobalt_lcdfb_probe,
+ .remove = __devexit_p(cobalt_lcdfb_remove),
+ .driver = {
+ .name = "cobalt-lcd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init cobalt_lcdfb_init(void)
+{
+ return platform_driver_register(&cobalt_lcdfb_driver);
+}
+
+static void __exit cobalt_lcdfb_exit(void)
+{
+ platform_driver_unregister(&cobalt_lcdfb_driver);
+}
+
+module_init(cobalt_lcdfb_init);
+module_exit(cobalt_lcdfb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yoichi Yuasa");
+MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 97aff8db10b..3ccfa76d9b2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,9 +107,7 @@ static struct display fb_display[MAX_NR_CONSOLES];
static signed char con2fb_map[MAX_NR_CONSOLES];
static signed char con2fb_map_boot[MAX_NR_CONSOLES];
-#ifndef MODULE
-static int logo_height;
-#endif
+
static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
@@ -607,6 +605,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
struct fbcon_ops *ops = info->fbcon_par;
int cnt, erase = vc->vc_video_erase_char, step;
unsigned short *save = NULL, *r, *q;
+ int logo_height;
if (info->flags & FBINFO_MODULE) {
logo_shown = FBCON_LOGO_DONTSHOW;
@@ -3586,7 +3585,8 @@ static int __init fb_console_init(void)
acquire_console_sem();
fb_register_client(&fbcon_event_notifier);
- fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
+ fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
+ NULL, "fbcon");
if (IS_ERR(fbcon_device)) {
printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 0135e039545..de1b1365279 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -92,7 +92,7 @@ struct fbcon_ops {
#define attr_fgcol(fgshift,s) \
(((s) >> (fgshift)) & 0x0f)
#define attr_bgcol(bgshift,s) \
- (((s) >> (bgshift)) & 0x0f)
+ (((s) >> (bgshift)) & 0x07)
/* Monochrome */
#define attr_bold(s) \
@@ -146,10 +146,8 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
return is_fg ? fg : bg;
}
-#define attr_bgcol_ec(bgshift,vc,info) \
- attr_col_ec(bgshift,vc,info,0);
-#define attr_fgcol_ec(fgshift,vc,info) \
- attr_col_ec(fgshift,vc,info,1);
+#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
+#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
/* Font */
#define REFCOUNT(fd) (((int *)(fd))[-1])
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 38a296bbdfc..9901064199b 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -71,13 +71,15 @@ static char *mda_type_name;
/* console information */
-static int mda_first_vc = 1;
+static int mda_first_vc = 13;
static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL;
module_param(mda_first_vc, int, 0);
+MODULE_PARM_DESC(mda_first_vc, "First virtual console. Default: 13");
module_param(mda_last_vc, int, 0);
+MODULE_PARM_DESC(mda_last_vc, "Last virtual console. Default: 16");
/* MDA register values
*/
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 33ebdb198da..5d84b343109 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -35,6 +35,7 @@
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>
+#include <linux/major.h>
#include <asm/fb.h>
@@ -848,9 +849,8 @@ int
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
{
struct fb_fix_screeninfo *fix = &info->fix;
- int xoffset = var->xoffset;
- int yoffset = var->yoffset;
- int err = 0, yres = info->var.yres;
+ unsigned int yres = info->var.yres;
+ int err = 0;
if (var->yoffset > 0) {
if (var->vmode & FB_VMODE_YWRAP) {
@@ -866,8 +866,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
(var->xoffset % fix->xpanstep)))
err = -EINVAL;
- if (err || !info->fbops->fb_pan_display || xoffset < 0 ||
- yoffset < 0 || var->yoffset + yres > info->var.yres_virtual ||
+ if (err || !info->fbops->fb_pan_display ||
+ var->yoffset + yres > info->var.yres_virtual ||
var->xoffset + info->var.xres > info->var.xres_virtual)
return -EINVAL;
@@ -1439,8 +1439,9 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->dev = device_create(fb_class, fb_info->device,
- MKDEV(FB_MAJOR, i), "fb%d", i);
+ fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
+ MKDEV(FB_MAJOR, i), NULL,
+ "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 052e1805849..6a0aa180c26 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -879,7 +879,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
if (edid_is_timing_block(block)) {
var->xres = var->xres_virtual = H_ACTIVE;
var->yres = var->yres_virtual = V_ACTIVE;
- var->height = var->width = -1;
+ var->height = var->width = 0;
var->right_margin = H_SYNC_OFFSET;
var->left_margin = (H_ACTIVE + H_BLANKING) -
(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 09d7e22c6fe..9cd36c223d3 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -279,58 +279,42 @@ static struct diu_hw dr = {
static struct diu_pool pool;
-/* To allocate memory for framebuffer. First try __get_free_pages(). If it
- * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate
- * very large memory (more than 4MB). We don't want to allocate all memory
- * in rheap since small memory allocation/deallocation will fragment the
- * rheap and make the furture large allocation fail.
+/**
+ * fsl_diu_alloc - allocate memory for the DIU
+ * @size: number of bytes to allocate
+ * @param: returned physical address of memory
+ *
+ * This function allocates a physically-contiguous block of memory.
*/
-
-static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
+static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
{
void *virt;
- pr_debug("size=%lu\n", size);
+ pr_debug("size=%zu\n", size);
- virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size));
+ virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
if (virt) {
*phys = virt_to_phys(virt);
- pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys);
- return virt;
- }
- if (!diu_ops.diu_mem) {
- printk(KERN_INFO "%s: no diu_mem."
- " To reserve more memory, put 'diufb=15M' "
- "in the command line\n", __func__);
- return NULL;
- }
-
- virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
- if (virt) {
- *phys = virt_to_bus(virt);
- memset(virt, 0, size);
+ pr_debug("virt=%p phys=%llx\n", virt,
+ (unsigned long long)*phys);
}
- pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
-
return virt;
}
-static void fsl_diu_free(void *p, unsigned long size)
+/**
+ * fsl_diu_free - release DIU memory
+ * @virt: pointer returned by fsl_diu_alloc()
+ * @size: number of bytes allocated by fsl_diu_alloc()
+ *
+ * This function releases memory allocated by fsl_diu_alloc().
+ */
+static void fsl_diu_free(void *virt, size_t size)
{
- pr_debug("p=%p size=%lu\n", p, size);
+ pr_debug("virt=%p size=%zu\n", virt, size);
- if (!p)
- return;
-
- if ((p >= diu_ops.diu_mem) &&
- (p < (diu_ops.diu_mem + diu_ops.diu_size))) {
- pr_debug("rh\n");
- rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
- } else {
- pr_debug("dma\n");
- free_pages((unsigned long)p, get_order(size));
- }
+ if (virt && size)
+ free_pages_exact(virt, size);
}
static int fsl_diu_enable_panel(struct fb_info *info)
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 3b9416f4ee2..6a51448fd3f 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -51,8 +51,6 @@ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
}
void lx_set_mode(struct fb_info *);
-void lx_get_gamma(struct fb_info *, unsigned int *, int);
-void lx_set_gamma(struct fb_info *, unsigned int *, int);
unsigned int lx_framebuffer_size(void);
int lx_blank_display(struct fb_info *, int);
void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
index aaef9165ec9..b1cd49c9935 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/geode/lxfb_ops.c
@@ -517,25 +517,25 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
int lx_blank_display(struct fb_info *info, int blank_mode)
{
struct lxfb_par *par = info->par;
- u32 dcfg, fp_pm;
- int blank, hsync, vsync, crt;
+ u32 dcfg, misc, fp_pm;
+ int blank, hsync, vsync;
/* CRT power saving modes. */
switch (blank_mode) {
case FB_BLANK_UNBLANK:
- blank = 0; hsync = 1; vsync = 1; crt = 1;
+ blank = 0; hsync = 1; vsync = 1;
break;
case FB_BLANK_NORMAL:
- blank = 1; hsync = 1; vsync = 1; crt = 1;
+ blank = 1; hsync = 1; vsync = 1;
break;
case FB_BLANK_VSYNC_SUSPEND:
- blank = 1; hsync = 1; vsync = 0; crt = 1;
+ blank = 1; hsync = 1; vsync = 0;
break;
case FB_BLANK_HSYNC_SUSPEND:
- blank = 1; hsync = 0; vsync = 1; crt = 1;
+ blank = 1; hsync = 0; vsync = 1;
break;
case FB_BLANK_POWERDOWN:
- blank = 1; hsync = 0; vsync = 0; crt = 0;
+ blank = 1; hsync = 0; vsync = 0;
break;
default:
return -EINVAL;
@@ -545,15 +545,23 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
VP_DCFG_CRT_EN);
if (!blank)
- dcfg |= VP_DCFG_DAC_BL_EN;
+ dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
if (hsync)
dcfg |= VP_DCFG_HSYNC_EN;
if (vsync)
dcfg |= VP_DCFG_VSYNC_EN;
- if (crt)
- dcfg |= VP_DCFG_CRT_EN;
+
write_vp(par, VP_DCFG, dcfg);
+ misc = read_vp(par, VP_MISC);
+
+ if (vsync && hsync)
+ misc &= ~VP_MISC_DACPWRDN;
+ else
+ misc |= VP_MISC_DACPWRDN;
+
+ write_vp(par, VP_MISC, misc);
+
/* Power on/off flat panel */
if (par->output & OUTPUT_PANEL) {
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index c18880d9db1..0129c044f6d 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-static int __init hgafb_probe(struct device *device)
+static int __init hgafb_probe(struct platform_device *pdev)
{
struct fb_info *info;
@@ -565,7 +565,7 @@ static int __init hgafb_probe(struct device *device)
printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
hga_type_name, hga_vram_len/1024);
- info = framebuffer_alloc(0, NULL);
+ info = framebuffer_alloc(0, &pdev->dev);
if (!info) {
iounmap(hga_vram);
return -ENOMEM;
@@ -593,13 +593,13 @@ static int __init hgafb_probe(struct device *device)
printk(KERN_INFO "fb%d: %s frame buffer device\n",
info->node, info->fix.id);
- dev_set_drvdata(device, info);
+ platform_set_drvdata(pdev, info);
return 0;
}
-static int hgafb_remove(struct device *device)
+static int hgafb_remove(struct platform_device *pdev)
{
- struct fb_info *info = dev_get_drvdata(device);
+ struct fb_info *info = platform_get_drvdata(pdev);
hga_txt_mode();
hga_clear_screen();
@@ -620,16 +620,15 @@ static int hgafb_remove(struct device *device)
return 0;
}
-static struct device_driver hgafb_driver = {
- .name = "hgafb",
- .bus = &platform_bus_type,
+static struct platform_driver hgafb_driver = {
.probe = hgafb_probe,
.remove = hgafb_remove,
+ .driver = {
+ .name = "hgafb",
+ },
};
-static struct platform_device hgafb_device = {
- .name = "hgafb",
-};
+static struct platform_device *hgafb_device;
static int __init hgafb_init(void)
{
@@ -638,12 +637,15 @@ static int __init hgafb_init(void)
if (fb_get_options("hgafb", NULL))
return -ENODEV;
- ret = driver_register(&hgafb_driver);
+ ret = platform_driver_register(&hgafb_driver);
if (!ret) {
- ret = platform_device_register(&hgafb_device);
- if (ret)
- driver_unregister(&hgafb_driver);
+ hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
+
+ if (IS_ERR(hgafb_device)) {
+ platform_driver_unregister(&hgafb_driver);
+ ret = PTR_ERR(hgafb_device);
+ }
}
return ret;
@@ -651,8 +653,8 @@ static int __init hgafb_init(void)
static void __exit hgafb_exit(void)
{
- platform_device_unregister(&hgafb_device);
- driver_unregister(&hgafb_driver);
+ platform_device_unregister(hgafb_device);
+ platform_driver_unregister(&hgafb_driver);
}
/* -------------------------------------------------------------------------
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 94e4d3ac1a0..0c5a475c1ca 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -24,6 +24,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 5246b0402d7..25172b2a2a9 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth)
*
* Determine the closest clock frequency to the one requested.
*/
-#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
#define MAX_N 127
#define MAX_D 31
#define MAX_F 1
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info,
{
int n, d, f;
int n_best = 0, d_best = 0, f_best = 0;
- long f_best_diff = (0x7ffff << 12); /* 20.12 */
- long f_target = (freq << 12) / 1000; /* 20.12 */
+ long f_best_diff = 0x7ffff;
for (f = 0; f <= MAX_F; f++)
- for (n = 0; n <= MAX_N; n++)
- for (d = 0; d <= MAX_D; d++) {
- long f_out; /* 20.12 */
- long f_diff; /* 20.12 */
-
- f_out =
- ((((n + 1) << 12) / ((d +
- 1) *
- (1 << f))) >> 12)
- * REF_FREQ;
- f_diff = abs(f_out - f_target);
- if (f_diff < f_best_diff) {
+ for (d = 0; d <= MAX_D; d++)
+ for (n = 0; n <= MAX_N; n++) {
+ long f_out;
+ long f_diff;
+
+ f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
+ f_diff = abs(f_out - freq);
+ if (f_diff <= f_best_diff) {
f_best_diff = f_diff;
n_best = n;
d_best = d;
f_best = f;
}
+ if (f_out > freq)
+ break;
}
if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info,
par->VCLK3Denominator = d_best;
#ifdef NEOFB_DEBUG
- printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
- f_target >> 12,
+ printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
+ freq,
par->VCLK3NumeratorLow,
par->VCLK3NumeratorHigh,
- par->VCLK3Denominator, f_best_diff >> 12);
+ par->VCLK3Denominator, f_best_diff);
#endif
}
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info,
*/
static int vgaHWInit(const struct fb_var_screeninfo *var,
- const struct fb_info *info,
- struct neofb_par *par, struct xtimings *timings)
+ struct neofb_par *par)
{
+ int hsync_end = var->xres + var->right_margin + var->hsync_len;
+ int htotal = (hsync_end + var->left_margin) >> 3;
+ int vsync_start = var->yres + var->lower_margin;
+ int vsync_end = vsync_start + var->vsync_len;
+ int vtotal = vsync_end + var->upper_margin;
+
par->MiscOutReg = 0x23;
- if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
par->MiscOutReg |= 0x40;
- if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
par->MiscOutReg |= 0x80;
/*
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
/*
* CRTC Controller
*/
- par->CRTC[0] = (timings->HTotal >> 3) - 5;
- par->CRTC[1] = (timings->HDisplay >> 3) - 1;
- par->CRTC[2] = (timings->HDisplay >> 3) - 1;
- par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
- par->CRTC[4] = (timings->HSyncStart >> 3);
- par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
- | (((timings->HSyncEnd >> 3)) & 0x1F);
- par->CRTC[6] = (timings->VTotal - 2) & 0xFF;
- par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8)
- | (((timings->VDisplay - 1) & 0x100) >> 7)
- | ((timings->VSyncStart & 0x100) >> 6)
- | (((timings->VDisplay - 1) & 0x100) >> 5)
- | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4)
- | (((timings->VDisplay - 1) & 0x200) >> 3)
- | ((timings->VSyncStart & 0x200) >> 2);
+ par->CRTC[0] = htotal - 5;
+ par->CRTC[1] = (var->xres >> 3) - 1;
+ par->CRTC[2] = (var->xres >> 3) - 1;
+ par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
+ par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
+ par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
+ | (((hsync_end >> 3)) & 0x1F);
+ par->CRTC[6] = (vtotal - 2) & 0xFF;
+ par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
+ | (((var->yres - 1) & 0x100) >> 7)
+ | ((vsync_start & 0x100) >> 6)
+ | (((var->yres - 1) & 0x100) >> 5)
+ | 0x10 | (((vtotal - 2) & 0x200) >> 4)
+ | (((var->yres - 1) & 0x200) >> 3)
+ | ((vsync_start & 0x200) >> 2);
par->CRTC[8] = 0x00;
- par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
+ par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
- if (timings->dblscan)
+ if (var->vmode & FB_VMODE_DOUBLE)
par->CRTC[9] |= 0x80;
par->CRTC[10] = 0x00;
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
par->CRTC[13] = 0x00;
par->CRTC[14] = 0x00;
par->CRTC[15] = 0x00;
- par->CRTC[16] = timings->VSyncStart & 0xFF;
- par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
- par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
+ par->CRTC[16] = vsync_start & 0xFF;
+ par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
+ par->CRTC[18] = (var->yres - 1) & 0xFF;
par->CRTC[19] = var->xres_virtual >> 4;
par->CRTC[20] = 0x00;
- par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;
- par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
+ par->CRTC[21] = (var->yres - 1) & 0xFF;
+ par->CRTC[22] = (vtotal - 1) & 0xFF;
par->CRTC[23] = 0xC3;
par->CRTC[24] = 0xFF;
@@ -483,7 +484,8 @@ static inline int neo2200_sync(struct fb_info *info)
{
struct neofb_par *par = info->par;
- while (readl(&par->neo2200->bltStat) & 1);
+ while (readl(&par->neo2200->bltStat) & 1)
+ cpu_relax();
return 0;
}
@@ -591,34 +593,14 @@ static int
neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct neofb_par *par = info->par;
- unsigned int pixclock = var->pixclock;
- struct xtimings timings;
int memlen, vramlen;
int mode_ok = 0;
DBG("neofb_check_var");
- if (!pixclock)
- pixclock = 10000; /* 10ns = 100MHz */
- timings.pixclock = 1000000000 / pixclock;
- if (timings.pixclock < 1)
- timings.pixclock = 1;
-
- if (timings.pixclock > par->maxClock)
+ if (PICOS2KHZ(var->pixclock) > par->maxClock)
return -EINVAL;
- timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
- timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
- timings.HDisplay = var->xres;
- timings.HSyncStart = timings.HDisplay + var->right_margin;
- timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
- timings.HTotal = timings.HSyncEnd + var->left_margin;
- timings.VDisplay = var->yres;
- timings.VSyncStart = timings.VDisplay + var->lower_margin;
- timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
- timings.VTotal = timings.VSyncEnd + var->upper_margin;
- timings.sync = var->sync;
-
/* Is the mode larger than the LCD panel? */
if (par->internal_display &&
((var->xres > par->NeoPanelWidth) ||
@@ -759,11 +741,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int neofb_set_par(struct fb_info *info)
{
struct neofb_par *par = info->par;
- struct xtimings timings;
unsigned char temp;
int i, clock_hi = 0;
int lcd_stretch;
int hoffset, voffset;
+ int vsync_start, vtotal;
DBG("neofb_set_par");
@@ -771,28 +753,15 @@ static int neofb_set_par(struct fb_info *info)
vgaHWProtect(1); /* Blank the screen */
- timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE;
- timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED;
- timings.HDisplay = info->var.xres;
- timings.HSyncStart = timings.HDisplay + info->var.right_margin;
- timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
- timings.HTotal = timings.HSyncEnd + info->var.left_margin;
- timings.VDisplay = info->var.yres;
- timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
- timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
- timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
- timings.sync = info->var.sync;
- timings.pixclock = PICOS2KHZ(info->var.pixclock);
-
- if (timings.pixclock < 1)
- timings.pixclock = 1;
+ vsync_start = info->var.yres + info->var.lower_margin;
+ vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
/*
* This will allocate the datastructure and initialize all of the
* generic VGA registers.
*/
- if (vgaHWInit(&info->var, info, par, &timings))
+ if (vgaHWInit(&info->var, par))
return -EINVAL;
/*
@@ -831,10 +800,10 @@ static int neofb_set_par(struct fb_info *info)
par->ExtCRTDispAddr = 0x10;
/* Vertical Extension */
- par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10)
- | (((timings.VDisplay - 1) & 0x400) >> 9)
- | (((timings.VSyncStart) & 0x400) >> 8)
- | (((timings.VSyncStart) & 0x400) >> 7);
+ par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
+ | (((info->var.yres - 1) & 0x400) >> 9)
+ | (((vsync_start) & 0x400) >> 8)
+ | (((vsync_start) & 0x400) >> 7);
/* Fast write bursts on unless disabled. */
if (par->pci_burst)
@@ -995,7 +964,7 @@ static int neofb_set_par(struct fb_info *info)
* Calculate the VCLK that most closely matches the requested dot
* clock.
*/
- neoCalcVCLK(info, par, timings.pixclock);
+ neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
/* Since we program the clocks ourselves, always use VCLK3. */
par->MiscOutReg |= 0x0C;
@@ -1927,9 +1896,6 @@ static int __devinit neo_init_hw(struct fb_info *info)
int maxClock = 65000;
int CursorMem = 1024;
int CursorOff = 0x100;
- int linearSize = 1024;
- int maxWidth = 1024;
- int maxHeight = 1024;
DBG("neo_init_hw");
@@ -1948,81 +1914,52 @@ static int __devinit neo_init_hw(struct fb_info *info)
case FB_ACCEL_NEOMAGIC_NM2070:
videoRam = 896;
maxClock = 65000;
- CursorMem = 2048;
- CursorOff = 0x100;
- linearSize = 1024;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2090:
case FB_ACCEL_NEOMAGIC_NM2093:
- videoRam = 1152;
- maxClock = 80000;
- CursorMem = 2048;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
- break;
case FB_ACCEL_NEOMAGIC_NM2097:
videoRam = 1152;
maxClock = 80000;
- CursorMem = 1024;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2160:
videoRam = 2048;
maxClock = 90000;
- CursorMem = 1024;
- CursorOff = 0x100;
- linearSize = 2048;
- maxWidth = 1024;
- maxHeight = 1024;
break;
case FB_ACCEL_NEOMAGIC_NM2200:
videoRam = 2560;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
videoRam = 3008;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
videoRam = 4096;
maxClock = 110000;
- CursorMem = 1024;
- CursorOff = 0x1000;
- linearSize = 4096;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
-
- par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
videoRam = 6144;
maxClock = 110000;
+ break;
+ }
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ CursorMem = 2048;
+ CursorOff = 0x100;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ CursorMem = 1024;
+ CursorOff = 0x100;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
CursorMem = 1024;
CursorOff = 0x1000;
- linearSize = 8192;
- maxWidth = 1280;
- maxHeight = 1024; /* ???? */
par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
break;
@@ -2036,7 +1973,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
*/
par->maxClock = maxClock;
par->cursorOff = CursorOff;
- return ((videoRam * 1024));
+ return videoRam * 1024;
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index d7b3dcc0dc4..e1d9eeb1aea 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -47,6 +47,7 @@ enum {
cmap_M3B, /* ATI Rage Mobility M3 Head B */
cmap_radeon, /* ATI Radeon */
cmap_gxt2000, /* IBM GXT2000 */
+ cmap_avivo, /* ATI R5xx */
};
struct offb_par {
@@ -58,26 +59,36 @@ struct offb_par {
struct offb_par default_par;
- /*
- * Interface used by the world
- */
-
-static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
-static int offb_blank(int blank, struct fb_info *info);
-
#ifdef CONFIG_PPC32
extern boot_infos_t *boot_infos;
#endif
-static struct fb_ops offb_ops = {
- .owner = THIS_MODULE,
- .fb_setcolreg = offb_setcolreg,
- .fb_blank = offb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
-};
+/* Definitions used by the Avivo palette hack */
+#define AVIVO_DC_LUT_RW_SELECT 0x6480
+#define AVIVO_DC_LUT_RW_MODE 0x6484
+#define AVIVO_DC_LUT_RW_INDEX 0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR 0x648c
+#define AVIVO_DC_LUT_PWL_DATA 0x6490
+#define AVIVO_DC_LUT_30_COLOR 0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
+#define AVIVO_DC_LUT_AUTOFILL 0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL 0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
+
+#define AVIVO_DC_LUTB_CONTROL 0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
/*
* Set a single color register. The values supplied are already
@@ -160,6 +171,17 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
(red << 16 | green << 8 | blue));
break;
+ case cmap_avivo:
+ /* Write to both LUTs for now */
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+ par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+ par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ break;
}
return 0;
@@ -216,12 +238,59 @@ static int offb_blank(int blank, struct fb_info *info)
out_le32(((unsigned __iomem *) par->cmap_adr) + i,
0);
break;
+ case cmap_avivo:
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+ break;
}
} else
fb_set_cmap(&info->cmap, info);
return 0;
}
+static int offb_set_par(struct fb_info *info)
+{
+ struct offb_par *par = (struct offb_par *) info->par;
+
+ /* On avivo, initialize palette control */
+ if (par->cmap_type == cmap_avivo) {
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
+ writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
+ writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
+ writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+ writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+ writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+ writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+ }
+ return 0;
+}
+
+static struct fb_ops offb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = offb_setcolreg,
+ .fb_set_par = offb_set_par,
+ .fb_blank = offb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
static void __iomem *offb_map_reg(struct device_node *np, int index,
unsigned long offset, unsigned long size)
@@ -245,6 +314,59 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
return ioremap(taddr + offset, size);
}
+static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
+ const char *name, unsigned long address)
+{
+ struct offb_par *par = (struct offb_par *) info->par;
+
+ if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+ par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_r128;
+ } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+ || !strncmp(name, "ATY,RageM3p12A", 14))) {
+ par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_M3A;
+ } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+ par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_M3B;
+ } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+ par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_radeon;
+ } else if (!strncmp(name, "ATY,", 4)) {
+ unsigned long base = address & 0xff000000UL;
+ par->cmap_adr =
+ ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
+ par->cmap_data = par->cmap_adr + 1;
+ par->cmap_type = cmap_m64;
+ } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+ of_device_is_compatible(dp, "pci1014,21c"))) {
+ par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_gxt2000;
+ } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+ /* Look for AVIVO initialized by SLOF */
+ struct device_node *pciparent = of_get_parent(dp);
+ const u32 *vid, *did;
+ vid = of_get_property(pciparent, "vendor-id", NULL);
+ did = of_get_property(pciparent, "device-id", NULL);
+ /* This will match most R5xx */
+ if (vid && did && *vid == 0x1002 &&
+ ((*did >= 0x7100 && *did < 0x7800) ||
+ (*did >= 0x9400))) {
+ par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
+ if (par->cmap_adr)
+ par->cmap_type = cmap_avivo;
+ }
+ of_node_put(pciparent);
+ }
+ info->fix.visual = (par->cmap_type != cmap_unknown) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
+}
+
static void __init offb_init_fb(const char *name, const char *full_name,
int width, int height, int depth,
int pitch, unsigned long address,
@@ -283,6 +405,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fix = &info->fix;
var = &info->var;
+ info->par = par;
strcpy(fix->id, "OFfb ");
strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
@@ -298,39 +421,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fix->type_aux = 0;
par->cmap_type = cmap_unknown;
- if (depth == 8) {
- if (dp && !strncmp(name, "ATY,Rage128", 11)) {
- par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
- if (par->cmap_adr)
- par->cmap_type = cmap_r128;
- } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
- || !strncmp(name, "ATY,RageM3p12A", 14))) {
- par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
- if (par->cmap_adr)
- par->cmap_type = cmap_M3A;
- } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
- par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
- if (par->cmap_adr)
- par->cmap_type = cmap_M3B;
- } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
- par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
- if (par->cmap_adr)
- par->cmap_type = cmap_radeon;
- } else if (!strncmp(name, "ATY,", 4)) {
- unsigned long base = address & 0xff000000UL;
- par->cmap_adr =
- ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
- par->cmap_data = par->cmap_adr + 1;
- par->cmap_type = cmap_m64;
- } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
- of_device_is_compatible(dp, "pci1014,21c"))) {
- par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
- if (par->cmap_adr)
- par->cmap_type = cmap_gxt2000;
- }
- fix->visual = (par->cmap_type != cmap_unknown) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
- } else
+ if (depth == 8)
+ offb_init_palette_hacks(info, dp, name, address);
+ else
fix->visual = FB_VISUAL_TRUECOLOR;
var->xoffset = var->yoffset = 0;
@@ -395,7 +488,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
info->fbops = &offb_ops;
info->screen_base = ioremap(address, fix->smem_len);
- info->par = par;
info->pseudo_palette = (void *) (info + 1);
info->flags = FBINFO_DEFAULT | foreign_endian;
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index ab32ceb0617..ab77c51fe9d 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -20,6 +20,7 @@
*/
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
+#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/clk.h>
#include <linux/io.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 14d0f7a1114..f85af5c4fa6 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -25,6 +25,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/platform_device.h>
+#include <linux/mm.h>
#include <linux/uaccess.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index dc3af1c78c5..4b5d8077190 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1297,6 +1297,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
static struct ps3_system_bus_driver ps3fb_driver = {
.match_id = PS3_MATCH_ID_GRAPHICS,
+ .match_sub_id = PS3_MATCH_SUB_ID_FB,
.core.name = DEVICE_NAME,
.core.owner = THIS_MODULE,
.probe = ps3fb_probe,
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index d0746261c95..2b707a8ce5d 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -30,6 +30,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -40,6 +41,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
+#include <linux/mutex.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
@@ -227,6 +229,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
case 4: ret = LCCR3_4BPP; break;
case 8: ret = LCCR3_8BPP; break;
case 16: ret = LCCR3_16BPP; break;
+ case 24:
+ switch (var->red.length + var->green.length +
+ var->blue.length + var->transp.length) {
+ case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
+ case 19: ret = LCCR3_19BPP_P; break;
+ }
+ break;
+ case 32:
+ switch (var->red.length + var->green.length +
+ var->blue.length + var->transp.length) {
+ case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
+ case 19: ret = LCCR3_19BPP; break;
+ case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
+ case 25: ret = LCCR3_25BPP; break;
+ }
+ break;
}
return ret;
}
@@ -345,6 +363,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->green.offset = 5; var->green.length = 6;
var->blue.offset = 0; var->blue.length = 5;
var->transp.offset = var->transp.length = 0;
+ } else if (var->bits_per_pixel > 16) {
+ struct pxafb_mode_info *mode;
+
+ mode = pxafb_getmode(inf, var);
+ if (!mode)
+ return -EINVAL;
+
+ switch (mode->depth) {
+ case 18: /* RGB666 */
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 12; var->red.length = 6;
+ var->green.offset = 6; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 6;
+ break;
+ case 19: /* RGBT666 */
+ var->transp.offset = 18; var->transp.length = 1;
+ var->red.offset = 12; var->red.length = 6;
+ var->green.offset = 6; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 6;
+ break;
+ case 24: /* RGB888 */
+ var->transp.offset = var->transp.length = 0;
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ break;
+ case 25: /* RGBT888 */
+ var->transp.offset = 24; var->transp.length = 1;
+ var->red.offset = 16; var->red.length = 8;
+ var->green.offset = 8; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
} else {
var->red.offset = var->green.offset = 0;
var->blue.offset = var->transp.offset = 0;
@@ -376,7 +429,7 @@ static int pxafb_set_par(struct fb_info *info)
struct pxafb_info *fbi = (struct pxafb_info *)info;
struct fb_var_screeninfo *var = &info->var;
- if (var->bits_per_pixel == 16)
+ if (var->bits_per_pixel >= 16)
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
else if (!fbi->cmap_static)
fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +444,7 @@ static int pxafb_set_par(struct fb_info *info)
fbi->fb.fix.line_length = var->xres_virtual *
var->bits_per_pixel / 8;
- if (var->bits_per_pixel == 16)
+ if (var->bits_per_pixel >= 16)
fbi->palette_size = 0;
else
fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +457,7 @@ static int pxafb_set_par(struct fb_info *info)
*/
pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
- if (fbi->fb.var.bits_per_pixel == 16)
+ if (fbi->fb.var.bits_per_pixel >= 16)
fb_dealloc_cmap(&fbi->fb.cmap);
else
fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +884,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
case 4:
case 8:
case 16:
+ case 24:
+ case 32:
break;
default:
printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,6 +1023,11 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+ /* 18 bit interface */
+ if (fbi->fb.var.bits_per_pixel > 16) {
+ pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
+ pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
+ }
pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
@@ -1058,7 +1118,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
{
u_int old_state;
- down(&fbi->ctrlr_sem);
+ mutex_lock(&fbi->ctrlr_lock);
old_state = fbi->state;
@@ -1146,7 +1206,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
}
break;
}
- up(&fbi->ctrlr_sem);
+ mutex_unlock(&fbi->ctrlr_lock);
}
/*
@@ -1399,7 +1459,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
init_waitqueue_head(&fbi->ctrlr_wait);
INIT_WORK(&fbi->task, pxafb_task);
- init_MUTEX(&fbi->ctrlr_sem);
+ mutex_init(&fbi->ctrlr_lock);
init_completion(&fbi->disable_done);
#ifdef CONFIG_FB_PXA_SMARTPANEL
init_completion(&fbi->command_done);
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 8238dc82642..31541b86f13 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -106,7 +106,7 @@ struct pxafb_info {
volatile u_char state;
volatile u_char task_state;
- struct semaphore ctrlr_sem;
+ struct mutex ctrlr_lock;
wait_queue_head_t ctrlr_wait;
struct work_struct task;
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index ab2b2110478..78bcdbc3f48 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -167,6 +167,7 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -174,6 +175,7 @@
#include <linux/cpufreq.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -1107,7 +1109,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
{
u_int old_state;
- down(&fbi->ctrlr_sem);
+ mutex_lock(&fbi->ctrlr_lock);
old_state = fbi->state;
@@ -1192,7 +1194,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
}
break;
}
- up(&fbi->ctrlr_sem);
+ mutex_unlock(&fbi->ctrlr_lock);
}
/*
@@ -1444,7 +1446,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
init_waitqueue_head(&fbi->ctrlr_wait);
INIT_WORK(&fbi->task, sa1100fb_task);
- init_MUTEX(&fbi->ctrlr_sem);
+ mutex_init(&fbi->ctrlr_lock);
return fbi;
}
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index f465b27ed86..86831db9a04 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -100,7 +100,7 @@ struct sa1100fb_info {
volatile u_char state;
volatile u_char task_state;
- struct semaphore ctrlr_sem;
+ struct mutex ctrlr_lock;
wait_queue_head_t ctrlr_wait;
struct work_struct task;
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
new file mode 100644
index 00000000000..4d0e28c5790
--- /dev/null
+++ b/drivers/video/sh7760fb.c
@@ -0,0 +1,658 @@
+/*
+ * SH7760/SH7763 LCDC Framebuffer driver.
+ *
+ * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
+ * Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
+ *
+ * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
+ * for his original source and testing!
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/sh7760fb.h>
+
+struct sh7760fb_par {
+ void __iomem *base;
+ int irq;
+
+ struct sh7760fb_platdata *pd; /* display information */
+
+ dma_addr_t fbdma; /* physical address */
+
+ int rot; /* rotation enabled? */
+
+ u32 pseudo_palette[16];
+
+ struct platform_device *dev;
+ struct resource *ioarea;
+ struct completion vsync; /* vsync irq event */
+};
+
+static irqreturn_t sh7760fb_irq(int irq, void *data)
+{
+ struct completion *c = data;
+
+ complete(c);
+
+ return IRQ_HANDLED;
+}
+
+static void sh7760fb_wait_vsync(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+
+ if (par->pd->novsync)
+ return;
+
+ iowrite16(ioread16(par->base + LDINTR) & ~VINT_CHECK,
+ par->base + LDINTR);
+
+ if (par->irq < 0) {
+ /* poll for vert. retrace: status bit is sticky */
+ while (!(ioread16(par->base + LDINTR) & VINT_CHECK))
+ cpu_relax();
+ } else {
+ /* a "wait_for_irq_event(par->irq)" would be extremely nice */
+ init_completion(&par->vsync);
+ enable_irq(par->irq);
+ wait_for_completion(&par->vsync);
+ disable_irq_nosync(par->irq);
+ }
+}
+
+/* wait_for_lps - wait until power supply has reached a certain state. */
+static int wait_for_lps(struct sh7760fb_par *par, int val)
+{
+ int i = 100;
+ while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
+ msleep(1);
+
+ if (i <= 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/* en/disable the LCDC */
+static int sh7760fb_blank(int blank, struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ struct sh7760fb_platdata *pd = par->pd;
+ unsigned short cntr = ioread16(par->base + LDCNTR);
+ unsigned short intr = ioread16(par->base + LDINTR);
+ int lps;
+
+ if (blank == FB_BLANK_UNBLANK) {
+ intr |= VINT_START;
+ cntr = LDCNTR_DON2 | LDCNTR_DON;
+ lps = 3;
+ } else {
+ intr &= ~VINT_START;
+ cntr = LDCNTR_DON2;
+ lps = 0;
+ }
+
+ if (pd->blank)
+ pd->blank(blank);
+
+ iowrite16(intr, par->base + LDINTR);
+ iowrite16(cntr, par->base + LDCNTR);
+
+ return wait_for_lps(par, lps);
+}
+
+/* set color registers */
+static int sh7760fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ u32 s = cmap->start;
+ u32 l = cmap->len;
+ u16 *r = cmap->red;
+ u16 *g = cmap->green;
+ u16 *b = cmap->blue;
+ u32 col, tmo;
+ int ret;
+
+ ret = 0;
+
+ sh7760fb_wait_vsync(info);
+
+ /* request palette access */
+ iowrite16(LDPALCR_PALEN, par->base + LDPALCR);
+
+ /* poll for access grant */
+ tmo = 100;
+ while (!(ioread16(par->base + LDPALCR) & LDPALCR_PALS) && (--tmo))
+ cpu_relax();
+
+ if (!tmo) {
+ ret = 1;
+ dev_dbg(info->dev, "no palette access!\n");
+ goto out;
+ }
+
+ while (l && (s < 256)) {
+ col = ((*r) & 0xff) << 16;
+ col |= ((*g) & 0xff) << 8;
+ col |= ((*b) & 0xff);
+ col &= SH7760FB_PALETTE_MASK;
+
+ if (s < 16)
+ ((u32 *) (info->pseudo_palette))[s] = s;
+
+ s++;
+ l--;
+ r++;
+ g++;
+ b++;
+ }
+out:
+ iowrite16(0, par->base + LDPALCR);
+ return ret;
+}
+
+static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
+ unsigned long stride)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, "sh7760-lcdc");
+
+ fix->smem_start = (unsigned long)info->screen_base;
+ fix->smem_len = info->screen_size;
+
+ fix->line_length = stride;
+}
+
+static int sh7760fb_get_color_info(struct device *dev,
+ u16 lddfr, int *bpp, int *gray)
+{
+ int lbpp, lgray;
+
+ lgray = lbpp = 0;
+
+ switch (lddfr & LDDFR_COLOR_MASK) {
+ case LDDFR_1BPP_MONO:
+ lgray = 1;
+ lbpp = 1;
+ break;
+ case LDDFR_2BPP_MONO:
+ lgray = 1;
+ lbpp = 2;
+ break;
+ case LDDFR_4BPP_MONO:
+ lgray = 1;
+ case LDDFR_4BPP:
+ lbpp = 4;
+ break;
+ case LDDFR_6BPP_MONO:
+ lgray = 1;
+ case LDDFR_8BPP:
+ lbpp = 8;
+ break;
+ case LDDFR_16BPP_RGB555:
+ case LDDFR_16BPP_RGB565:
+ lbpp = 16;
+ lgray = 0;
+ break;
+ default:
+ dev_dbg(dev, "unsupported LDDFR bit depth.\n");
+ return -EINVAL;
+ }
+
+ if (bpp)
+ *bpp = lbpp;
+ if (gray)
+ *gray = lgray;
+
+ return 0;
+}
+
+static int sh7760fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct sh7760fb_par *par = info->par;
+ int ret, bpp;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+ if (ret)
+ return ret;
+
+ var->bits_per_pixel = bpp;
+
+ if ((var->grayscale) && (var->bits_per_pixel == 1))
+ fix->visual = FB_VISUAL_MONO10;
+ else if (var->bits_per_pixel >= 15)
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ else
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+
+ /* TODO: add some more validation here */
+ return 0;
+}
+
+/*
+ * sh7760fb_set_par - set videomode.
+ *
+ * NOTE: The rotation, grayscale and DSTN codepaths are
+ * totally untested!
+ */
+static int sh7760fb_set_par(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ struct fb_videomode *vm = par->pd->def_mode;
+ unsigned long sbase, dstn_off, ldsarl, stride;
+ unsigned short hsynp, hsynw, htcn, hdcn;
+ unsigned short vsynp, vsynw, vtln, vdln;
+ unsigned short lddfr, ldmtr;
+ int ret, bpp, gray;
+
+ par->rot = par->pd->rotate;
+
+ /* rotate only works with xres <= 320 */
+ if (par->rot && (vm->xres > 320)) {
+ dev_dbg(info->dev, "rotation disabled due to display size\n");
+ par->rot = 0;
+ }
+
+ /* calculate LCDC reg vals from display parameters */
+ hsynp = vm->right_margin + vm->xres;
+ hsynw = vm->hsync_len;
+ htcn = vm->left_margin + hsynp + hsynw;
+ hdcn = vm->xres;
+ vsynp = vm->lower_margin + vm->yres;
+ vsynw = vm->vsync_len;
+ vtln = vm->upper_margin + vsynp + vsynw;
+ vdln = vm->yres;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
+ if (ret)
+ return ret;
+
+ dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
+ vdln, bpp, gray ? "grayscale" : "color",
+ par->rot ? "rotated" : "normal");
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ lddfr = par->pd->lddfr | (1 << 8);
+#else
+ lddfr = par->pd->lddfr & ~(1 << 8);
+#endif
+
+ ldmtr = par->pd->ldmtr;
+
+ if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
+ ldmtr |= LDMTR_CL1POL;
+ if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
+ ldmtr |= LDMTR_FLMPOL;
+
+ /* shut down LCDC before changing display parameters */
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+
+ iowrite16(par->pd->ldickr, par->base + LDICKR); /* pixclock */
+ iowrite16(ldmtr, par->base + LDMTR); /* polarities */
+ iowrite16(lddfr, par->base + LDDFR); /* color/depth */
+ iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR); /* rotate */
+ iowrite16(par->pd->ldpmmr, par->base + LDPMMR); /* Power Management */
+ iowrite16(par->pd->ldpspr, par->base + LDPSPR); /* Power Supply Ctrl */
+
+ /* display resolution */
+ iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
+ par->base + LDHCNR);
+ iowrite16(vdln - 1, par->base + LDVDLNR);
+ iowrite16(vtln - 1, par->base + LDVTLNR);
+ /* h/v sync signals */
+ iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
+ iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
+ par->base + LDHSYNR);
+ /* AC modulation sig */
+ iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
+
+ stride = (par->rot) ? vtln : hdcn;
+ if (!gray)
+ stride *= (bpp + 7) >> 3;
+ else {
+ if (bpp == 1)
+ stride >>= 3;
+ else if (bpp == 2)
+ stride >>= 2;
+ else if (bpp == 4)
+ stride >>= 1;
+ /* 6 bpp == 8 bpp */
+ }
+
+ /* if rotated, stride must be power of 2 */
+ if (par->rot) {
+ unsigned long bit = 1 << 31;
+ while (bit) {
+ if (stride & bit)
+ break;
+ bit >>= 1;
+ }
+ if (stride & ~bit)
+ stride = bit << 1; /* not P-o-2, round up */
+ }
+ iowrite16(stride, par->base + LDLAOR);
+
+ /* set display mem start address */
+ sbase = (unsigned long)par->fbdma;
+ if (par->rot)
+ sbase += (hdcn - 1) * stride;
+
+ iowrite32(sbase, par->base + LDSARU);
+
+ /*
+ * for DSTN need to set address for lower half.
+ * I (mlau) don't know which address to set it to,
+ * so I guessed at (stride * yres/2).
+ */
+ if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
+ ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
+
+ dev_dbg(info->dev, " ***** DSTN untested! *****\n");
+
+ dstn_off = stride;
+ if (par->rot)
+ dstn_off *= hdcn >> 1;
+ else
+ dstn_off *= vdln >> 1;
+
+ ldsarl = sbase + dstn_off;
+ } else
+ ldsarl = 0;
+
+ iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */
+
+ encode_fix(&info->fix, info, stride);
+ sh7760fb_check_var(&info->var, info);
+
+ sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
+
+ dev_dbg(info->dev, "hdcn : %6d htcn : %6d\n", hdcn, htcn);
+ dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
+ dev_dbg(info->dev, "vdln : %6d vtln : %6d\n", vdln, vtln);
+ dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
+ dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
+ (par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
+ dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
+ par->pd->ldpspr);
+ dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
+ dev_dbg(info->dev, "ldlaor: %ld\n", stride);
+ dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
+
+ return 0;
+}
+
+static struct fb_ops sh7760fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_blank = sh7760fb_blank,
+ .fb_check_var = sh7760fb_check_var,
+ .fb_setcmap = sh7760fb_setcmap,
+ .fb_set_par = sh7760fb_set_par,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static void sh7760fb_free_mem(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+
+ if (!info->screen_base)
+ return;
+
+ dma_free_coherent(info->dev, info->screen_size,
+ info->screen_base, par->fbdma);
+
+ par->fbdma = 0;
+ info->screen_base = NULL;
+ info->screen_size = 0;
+}
+
+/* allocate the framebuffer memory. This memory must be in Area3,
+ * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
+ */
+static int sh7760fb_alloc_mem(struct fb_info *info)
+{
+ struct sh7760fb_par *par = info->par;
+ void *fbmem;
+ unsigned long vram;
+ int ret, bpp;
+
+ if (info->screen_base)
+ return 0;
+
+ /* get color info from register value */
+ ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
+ if (ret) {
+ printk(KERN_ERR "colinfo\n");
+ return ret;
+ }
+
+ /* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
+ max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
+
+ vram = info->var.xres * info->var.yres;
+ if (info->var.grayscale) {
+ if (bpp == 1)
+ vram >>= 3;
+ else if (bpp == 2)
+ vram >>= 2;
+ else if (bpp == 4)
+ vram >>= 1;
+ } else if (bpp > 8)
+ vram *= 2;
+ if ((vram < 1) || (vram > 1024 * 2048)) {
+ dev_dbg(info->dev, "too much VRAM required. Check settings\n");
+ return -ENODEV;
+ }
+
+ if (vram < PAGE_SIZE)
+ vram = PAGE_SIZE;
+
+ fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
+
+ if (!fbmem)
+ return -ENOMEM;
+
+ if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
+ sh7760fb_free_mem(info);
+ dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
+ "unusable for the LCDC\n", (unsigned long)par->fbdma);
+ return -ENOMEM;
+ }
+
+ info->screen_base = fbmem;
+ info->screen_size = vram;
+
+ return 0;
+}
+
+static int __devinit sh7760fb_probe(struct platform_device *pdev)
+{
+ struct fb_info *info;
+ struct resource *res;
+ struct sh7760fb_par *par;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(res == NULL)) {
+ dev_err(&pdev->dev, "invalid resource\n");
+ return -EINVAL;
+ }
+
+ info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->dev = pdev;
+
+ par->pd = pdev->dev.platform_data;
+ if (!par->pd) {
+ dev_dbg(info->dev, "no display setup data!\n");
+ ret = -ENODEV;
+ goto out_fb;
+ }
+
+ par->ioarea = request_mem_region(res->start,
+ (res->end - res->start), pdev->name);
+ if (!par->ioarea) {
+ dev_err(&pdev->dev, "mmio area busy\n");
+ ret = -EBUSY;
+ goto out_fb;
+ }
+
+ par->base = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (!par->base) {
+ dev_err(&pdev->dev, "cannot remap\n");
+ ret = -ENODEV;
+ goto out_res;
+ }
+
+ iowrite16(0, par->base + LDINTR); /* disable vsync irq */
+ par->irq = platform_get_irq(pdev, 0);
+ if (par->irq >= 0) {
+ ret = request_irq(par->irq, sh7760fb_irq, 0,
+ "sh7760-lcdc", &par->vsync);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot grab IRQ\n");
+ par->irq = -ENXIO;
+ } else
+ disable_irq_nosync(par->irq);
+ }
+
+ fb_videomode_to_var(&info->var, par->pd->def_mode);
+
+ ret = sh7760fb_alloc_mem(info);
+ if (ret) {
+ dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
+ goto out_unmap;
+ }
+
+ info->pseudo_palette = par->pseudo_palette;
+
+ /* fixup color register bitpositions. These are fixed by hardware */
+ info->var.red.offset = 11;
+ info->var.red.length = 5;
+ info->var.red.msb_right = 0;
+
+ info->var.green.offset = 5;
+ info->var.green.length = 6;
+ info->var.green.msb_right = 0;
+
+ info->var.blue.offset = 0;
+ info->var.blue.length = 5;
+ info->var.blue.msb_right = 0;
+
+ info->var.transp.offset = 0;
+ info->var.transp.length = 0;
+ info->var.transp.msb_right = 0;
+
+ /* set the DON2 bit now, before cmap allocation, as it will randomize
+ * palette memory.
+ */
+ iowrite16(LDCNTR_DON2, par->base + LDCNTR);
+ info->fbops = &sh7760fb_ops;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_dbg(info->dev, "Unable to allocate cmap memory\n");
+ goto out_mem;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_dbg(info->dev, "cannot register fb!\n");
+ goto out_cmap;
+ }
+ platform_set_drvdata(pdev, info);
+
+ printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
+ pdev->name,
+ (unsigned long)par->fbdma,
+ (unsigned long)(par->fbdma + info->screen_size - 1),
+ info->screen_size >> 10);
+
+ return 0;
+
+out_cmap:
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+ fb_dealloc_cmap(&info->cmap);
+out_mem:
+ sh7760fb_free_mem(info);
+out_unmap:
+ if (par->irq >= 0)
+ free_irq(par->irq, &par->vsync);
+ iounmap(par->base);
+out_res:
+ release_resource(par->ioarea);
+ kfree(par->ioarea);
+out_fb:
+ framebuffer_release(info);
+ return ret;
+}
+
+static int __devexit sh7760fb_remove(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+ struct sh7760fb_par *par = info->par;
+
+ sh7760fb_blank(FB_BLANK_POWERDOWN, info);
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ sh7760fb_free_mem(info);
+ if (par->irq >= 0)
+ free_irq(par->irq, par);
+ iounmap(par->base);
+ release_resource(par->ioarea);
+ kfree(par->ioarea);
+ framebuffer_release(info);
+ platform_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver sh7760_lcdc_driver = {
+ .driver = {
+ .name = "sh7760-lcdc",
+ .owner = THIS_MODULE,
+ },
+ .probe = sh7760fb_probe,
+ .remove = __devexit_p(sh7760fb_remove),
+};
+
+static int __init sh7760fb_init(void)
+{
+ return platform_driver_register(&sh7760_lcdc_driver);
+}
+
+static void __exit sh7760fb_exit(void)
+{
+ platform_driver_unregister(&sh7760_lcdc_driver);
+}
+
+module_init(sh7760fb_init);
+module_exit(sh7760fb_exit);
+
+MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
+MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
new file mode 100644
index 00000000000..f6ef6cca73c
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -0,0 +1,725 @@
+/*
+ * SuperH Mobile LCDC Framebuffer
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/sh_mobile_lcdc.h>
+
+#define PALETTE_NR 16
+
+struct sh_mobile_lcdc_priv;
+struct sh_mobile_lcdc_chan {
+ struct sh_mobile_lcdc_priv *lcdc;
+ unsigned long *reg_offs;
+ unsigned long ldmt1r_value;
+ unsigned long enabled; /* ME and SE in LDCNT2R */
+ struct sh_mobile_lcdc_chan_cfg cfg;
+ u32 pseudo_palette[PALETTE_NR];
+ struct fb_info info;
+ dma_addr_t dma_handle;
+};
+
+struct sh_mobile_lcdc_priv {
+ void __iomem *base;
+ struct clk *clk;
+ unsigned long lddckr;
+ struct sh_mobile_lcdc_chan ch[2];
+};
+
+/* shared registers */
+#define _LDDCKR 0x410
+#define _LDDCKSTPR 0x414
+#define _LDINTR 0x468
+#define _LDSR 0x46c
+#define _LDCNT1R 0x470
+#define _LDCNT2R 0x474
+#define _LDDDSR 0x47c
+#define _LDDWD0R 0x800
+#define _LDDRDR 0x840
+#define _LDDWAR 0x900
+#define _LDDRAR 0x904
+
+/* per-channel registers */
+enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
+ LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
+
+static unsigned long lcdc_offs_mainlcd[] = {
+ [LDDCKPAT1R] = 0x400,
+ [LDDCKPAT2R] = 0x404,
+ [LDMT1R] = 0x418,
+ [LDMT2R] = 0x41c,
+ [LDMT3R] = 0x420,
+ [LDDFR] = 0x424,
+ [LDSM1R] = 0x428,
+ [LDSA1R] = 0x430,
+ [LDMLSR] = 0x438,
+ [LDHCNR] = 0x448,
+ [LDHSYNR] = 0x44c,
+ [LDVLNR] = 0x450,
+ [LDVSYNR] = 0x454,
+ [LDPMR] = 0x460,
+};
+
+static unsigned long lcdc_offs_sublcd[] = {
+ [LDDCKPAT1R] = 0x408,
+ [LDDCKPAT2R] = 0x40c,
+ [LDMT1R] = 0x600,
+ [LDMT2R] = 0x604,
+ [LDMT3R] = 0x608,
+ [LDDFR] = 0x60c,
+ [LDSM1R] = 0x610,
+ [LDSA1R] = 0x618,
+ [LDMLSR] = 0x620,
+ [LDHCNR] = 0x624,
+ [LDHSYNR] = 0x628,
+ [LDVLNR] = 0x62c,
+ [LDVSYNR] = 0x630,
+ [LDPMR] = 0x63c,
+};
+
+#define START_LCDC 0x00000001
+#define LCDC_RESET 0x00000100
+#define DISPLAY_BEU 0x00000008
+#define LCDC_ENABLE 0x00000001
+
+static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
+ int reg_nr, unsigned long data)
+{
+ iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
+ int reg_nr)
+{
+ return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
+}
+
+static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs, unsigned long data)
+{
+ iowrite32(data, priv->base + reg_offs);
+}
+
+static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs)
+{
+ return ioread32(priv->base + reg_offs);
+}
+
+static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
+ unsigned long reg_offs,
+ unsigned long mask, unsigned long until)
+{
+ while ((lcdc_read(priv, reg_offs) & mask) != until)
+ cpu_relax();
+}
+
+static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+{
+ return chan->cfg.chan == LCDC_CHAN_SUBLCD;
+}
+
+static void lcdc_sys_write_index(void *handle, unsigned long data)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static void lcdc_sys_write_data(void *handle, unsigned long data)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+}
+
+static unsigned long lcdc_sys_read_data(void *handle)
+{
+ struct sh_mobile_lcdc_chan *ch = handle;
+
+ lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
+ lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
+ lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
+ udelay(1);
+
+ return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
+}
+
+struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+ lcdc_sys_write_index,
+ lcdc_sys_write_data,
+ lcdc_sys_read_data,
+};
+
+static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
+ int start)
+{
+ unsigned long tmp = lcdc_read(priv, _LDCNT2R);
+ int k;
+
+ /* start or stop the lcdc */
+ if (start)
+ lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
+ else
+ lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
+
+ /* wait until power is applied/stopped on all channels */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
+ if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
+ while (1) {
+ tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
+ if (start && tmp == 3)
+ break;
+ if (!start && tmp == 0)
+ break;
+ cpu_relax();
+ }
+
+ if (!start)
+ lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
+}
+
+static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+{
+ struct sh_mobile_lcdc_chan *ch;
+ struct fb_videomode *lcd_cfg;
+ struct sh_mobile_lcdc_board_cfg *board_cfg;
+ unsigned long tmp;
+ int k, m;
+ int ret = 0;
+
+ /* reset */
+ lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
+ lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
+
+ /* enable LCDC channels */
+ tmp = lcdc_read(priv, _LDCNT2R);
+ tmp |= priv->ch[0].enabled;
+ tmp |= priv->ch[1].enabled;
+ lcdc_write(priv, _LDCNT2R, tmp);
+
+ /* read data from external memory, avoid using the BEU for now */
+ lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
+
+ /* stop the lcdc first */
+ sh_mobile_lcdc_start_stop(priv, 0);
+
+ /* configure clocks */
+ tmp = priv->lddckr;
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+
+ if (!priv->ch[k].enabled)
+ continue;
+
+ m = ch->cfg.clock_divider;
+ if (!m)
+ continue;
+
+ if (m == 1)
+ m = 1 << 6;
+ tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
+
+ lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
+ lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
+ }
+
+ lcdc_write(priv, _LDDCKR, tmp);
+
+ /* start dotclock again */
+ lcdc_write(priv, _LDDCKSTPR, 0);
+ lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
+
+ /* interrupts are disabled */
+ lcdc_write(priv, _LDINTR, 0);
+
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ lcd_cfg = &ch->cfg.lcd_cfg;
+
+ if (!ch->enabled)
+ continue;
+
+ tmp = ch->ldmt1r_value;
+ tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
+ tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
+ lcdc_write_chan(ch, LDMT1R, tmp);
+
+ /* setup SYS bus */
+ lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
+ lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
+
+ /* horizontal configuration */
+ tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
+ tmp += lcd_cfg->left_margin;
+ tmp += lcd_cfg->right_margin;
+ tmp /= 8; /* HTCN */
+ tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
+ lcdc_write_chan(ch, LDHCNR, tmp);
+
+ tmp = lcd_cfg->xres;
+ tmp += lcd_cfg->right_margin;
+ tmp /= 8; /* HSYNP */
+ tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
+ lcdc_write_chan(ch, LDHSYNR, tmp);
+
+ /* power supply */
+ lcdc_write_chan(ch, LDPMR, 0);
+
+ /* vertical configuration */
+ tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
+ tmp += lcd_cfg->upper_margin;
+ tmp += lcd_cfg->lower_margin; /* VTLN */
+ tmp |= lcd_cfg->yres << 16; /* VDLN */
+ lcdc_write_chan(ch, LDVLNR, tmp);
+
+ tmp = lcd_cfg->yres;
+ tmp += lcd_cfg->lower_margin; /* VSYNP */
+ tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
+ lcdc_write_chan(ch, LDVSYNR, tmp);
+
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->setup_sys)
+ ret = board_cfg->setup_sys(board_cfg->board_data, ch,
+ &sh_mobile_lcdc_sys_bus_ops);
+ if (ret)
+ return ret;
+ }
+
+ /* --- display_lcdc_data() --- */
+ lcdc_write(priv, _LDINTR, 0x00000f00);
+
+ /* word and long word swap */
+ lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
+
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+
+ if (!priv->ch[k].enabled)
+ continue;
+
+ /* set bpp format in PKF[4:0] */
+ tmp = lcdc_read_chan(ch, LDDFR);
+ tmp &= ~(0x0001001f);
+ tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
+ lcdc_write_chan(ch, LDDFR, tmp);
+
+ /* point out our frame buffer */
+ lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
+
+ /* set line size */
+ lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
+
+ /* continuous read mode */
+ lcdc_write_chan(ch, LDSM1R, 0);
+ }
+
+ /* display output */
+ lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
+
+ /* start the lcdc */
+ sh_mobile_lcdc_start_stop(priv, 1);
+
+ /* tell the board code to enable the panel */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->display_on)
+ board_cfg->display_on(board_cfg->board_data);
+ }
+
+ return 0;
+}
+
+static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+{
+ struct sh_mobile_lcdc_chan *ch;
+ struct sh_mobile_lcdc_board_cfg *board_cfg;
+ int k;
+
+ /* tell the board code to disable the panel */
+ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ ch = &priv->ch[k];
+ board_cfg = &ch->cfg.board_cfg;
+ if (board_cfg->display_off)
+ board_cfg->display_off(board_cfg->board_data);
+ }
+
+ /* stop the lcdc */
+ sh_mobile_lcdc_start_stop(priv, 0);
+}
+
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+{
+ int ifm, miftyp;
+
+ switch (ch->cfg.interface_type) {
+ case RGB8: ifm = 0; miftyp = 0; break;
+ case RGB9: ifm = 0; miftyp = 4; break;
+ case RGB12A: ifm = 0; miftyp = 5; break;
+ case RGB12B: ifm = 0; miftyp = 6; break;
+ case RGB16: ifm = 0; miftyp = 7; break;
+ case RGB18: ifm = 0; miftyp = 10; break;
+ case RGB24: ifm = 0; miftyp = 11; break;
+ case SYS8A: ifm = 1; miftyp = 0; break;
+ case SYS8B: ifm = 1; miftyp = 1; break;
+ case SYS8C: ifm = 1; miftyp = 2; break;
+ case SYS8D: ifm = 1; miftyp = 3; break;
+ case SYS9: ifm = 1; miftyp = 4; break;
+ case SYS12: ifm = 1; miftyp = 5; break;
+ case SYS16A: ifm = 1; miftyp = 7; break;
+ case SYS16B: ifm = 1; miftyp = 8; break;
+ case SYS16C: ifm = 1; miftyp = 9; break;
+ case SYS18: ifm = 1; miftyp = 10; break;
+ case SYS24: ifm = 1; miftyp = 11; break;
+ default: goto bad;
+ }
+
+ /* SUBLCD only supports SYS interface */
+ if (lcdc_chan_is_sublcd(ch)) {
+ if (ifm == 0)
+ goto bad;
+ else
+ ifm = 0;
+ }
+
+ ch->ldmt1r_value = (ifm << 12) | miftyp;
+ return 0;
+ bad:
+ return -EINVAL;
+}
+
+static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
+ struct sh_mobile_lcdc_priv *priv)
+{
+ char *str;
+ int icksel;
+
+ switch (clock_source) {
+ case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
+ case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
+ case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
+ default:
+ return -EINVAL;
+ }
+
+ priv->lddckr = icksel << 16;
+
+ if (str) {
+ priv->clk = clk_get(dev, str);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "cannot get clock %s\n", str);
+ return PTR_ERR(priv->clk);
+ }
+
+ clk_enable(priv->clk);
+ }
+
+ return 0;
+}
+
+static int sh_mobile_lcdc_setcolreg(u_int regno,
+ u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ u32 *palette = info->pseudo_palette;
+
+ if (regno >= PALETTE_NR)
+ return -EINVAL;
+
+ /* only FB_VISUAL_TRUECOLOR supported */
+
+ red >>= 16 - info->var.red.length;
+ green >>= 16 - info->var.green.length;
+ blue >>= 16 - info->var.blue.length;
+ transp >>= 16 - info->var.transp.length;
+
+ palette[regno] = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ return 0;
+}
+
+static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
+ .id = "SH Mobile LCDC",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static struct fb_ops sh_mobile_lcdc_ops = {
+ .fb_setcolreg = sh_mobile_lcdc_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
+{
+ switch (bpp) {
+ case 16: /* PKF[4:0] = 00011 - RGB 565 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+
+ case 32: /* PKF[4:0] = 00000 - RGB 888
+ * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
+ * this may be because LDDDSR has word swap enabled..
+ */
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 24;
+ var->green.length = 8;
+ var->blue.offset = 16;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ var->bits_per_pixel = bpp;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ return 0;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev);
+
+static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
+{
+ struct fb_info *info;
+ struct sh_mobile_lcdc_priv *priv;
+ struct sh_mobile_lcdc_info *pdata;
+ struct sh_mobile_lcdc_chan_cfg *cfg;
+ struct resource *res;
+ int error;
+ void *buf;
+ int i, j;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ error = -EINVAL;
+ goto err0;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "cannot find IO resource\n");
+ error = -ENOENT;
+ goto err0;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "cannot allocate device data\n");
+ error = -ENOMEM;
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ pdata = pdev->dev.platform_data;
+
+ j = 0;
+ for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
+ priv->ch[j].lcdc = priv;
+ memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
+
+ error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
+ if (error) {
+ dev_err(&pdev->dev, "unsupported interface type\n");
+ goto err1;
+ }
+
+ switch (pdata->ch[i].chan) {
+ case LCDC_CHAN_MAINLCD:
+ priv->ch[j].enabled = 1 << 1;
+ priv->ch[j].reg_offs = lcdc_offs_mainlcd;
+ j++;
+ break;
+ case LCDC_CHAN_SUBLCD:
+ priv->ch[j].enabled = 1 << 2;
+ priv->ch[j].reg_offs = lcdc_offs_sublcd;
+ j++;
+ break;
+ }
+ }
+
+ if (!j) {
+ dev_err(&pdev->dev, "no channels defined\n");
+ error = -EINVAL;
+ goto err1;
+ }
+
+ error = sh_mobile_lcdc_setup_clocks(&pdev->dev,
+ pdata->clock_source, priv);
+ if (error) {
+ dev_err(&pdev->dev, "unable to setup clocks\n");
+ goto err1;
+ }
+
+ priv->lddckr = pdata->lddckr;
+ priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
+
+ for (i = 0; i < j; i++) {
+ info = &priv->ch[i].info;
+ cfg = &priv->ch[i].cfg;
+
+ info->fbops = &sh_mobile_lcdc_ops;
+ info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
+ info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
+ info->var.activate = FB_ACTIVATE_NOW;
+ error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
+ if (error)
+ break;
+
+ info->fix = sh_mobile_lcdc_fix;
+ info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
+ info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres;
+
+ buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
+ &priv->ch[i].dma_handle, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&pdev->dev, "unable to allocate buffer\n");
+ error = -ENOMEM;
+ break;
+ }
+
+ info->pseudo_palette = &priv->ch[i].pseudo_palette;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
+ if (error < 0) {
+ dev_err(&pdev->dev, "unable to allocate cmap\n");
+ dma_free_coherent(&pdev->dev, info->fix.smem_len,
+ buf, priv->ch[i].dma_handle);
+ break;
+ }
+
+ memset(buf, 0, info->fix.smem_len);
+ info->fix.smem_start = priv->ch[i].dma_handle;
+ info->screen_base = buf;
+ info->device = &pdev->dev;
+ }
+
+ if (error)
+ goto err1;
+
+ error = sh_mobile_lcdc_start(priv);
+ if (error) {
+ dev_err(&pdev->dev, "unable to start hardware\n");
+ goto err1;
+ }
+
+ for (i = 0; i < j; i++) {
+ error = register_framebuffer(&priv->ch[i].info);
+ if (error < 0)
+ goto err1;
+ }
+
+ for (i = 0; i < j; i++) {
+ info = &priv->ch[i].info;
+ dev_info(info->dev,
+ "registered %s/%s as %dx%d %dbpp.\n",
+ pdev->name,
+ (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
+ "mainlcd" : "sublcd",
+ (int) priv->ch[i].cfg.lcd_cfg.xres,
+ (int) priv->ch[i].cfg.lcd_cfg.yres,
+ priv->ch[i].cfg.bpp);
+ }
+
+ return 0;
+ err1:
+ sh_mobile_lcdc_remove(pdev);
+ err0:
+ return error;
+}
+
+static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+{
+ struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+ struct fb_info *info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+ if (priv->ch[i].info.dev)
+ unregister_framebuffer(&priv->ch[i].info);
+
+ sh_mobile_lcdc_stop(priv);
+
+ for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+ info = &priv->ch[i].info;
+
+ if (!info->device)
+ continue;
+
+ dma_free_coherent(&pdev->dev, info->fix.smem_len,
+ info->screen_base, priv->ch[i].dma_handle);
+ fb_dealloc_cmap(&info->cmap);
+ }
+
+ if (priv->clk) {
+ clk_disable(priv->clk);
+ clk_put(priv->clk);
+ }
+
+ if (priv->base)
+ iounmap(priv->base);
+
+ kfree(priv);
+ return 0;
+}
+
+static struct platform_driver sh_mobile_lcdc_driver = {
+ .driver = {
+ .name = "sh_mobile_lcdc_fb",
+ .owner = THIS_MODULE,
+ },
+ .probe = sh_mobile_lcdc_probe,
+ .remove = sh_mobile_lcdc_remove,
+};
+
+static int __init sh_mobile_lcdc_init(void)
+{
+ return platform_driver_register(&sh_mobile_lcdc_driver);
+}
+
+static void __exit sh_mobile_lcdc_exit(void)
+{
+ platform_driver_unregister(&sh_mobile_lcdc_driver);
+}
+
+module_init(sh_mobile_lcdc_init);
+module_exit(sh_mobile_lcdc_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index f40a680df86..b96005c39c6 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -73,7 +73,6 @@
#ifdef SIS_CP
#undef SIS_CP
#endif
-#include <linux/version.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 7708e1e1d99..51d99222375 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -67,7 +67,6 @@
#ifdef SIS_CP
#undef SIS_CP
#endif
-#include <linux/version.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index 47a33501549..99c04a4855d 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -30,7 +30,6 @@
#include "vgatypes.h"
#include "vstruct.h"
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
index c1492782cb1..6ff8f988a1a 100644
--- a/drivers/video/sis/osdef.h
+++ b/drivers/video/sis/osdef.h
@@ -87,7 +87,6 @@
/**********************************************************************/
#ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
#ifdef CONFIG_FB_SIS_300
#define SIS300
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index a14e8221103..7c5710e3fb5 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -24,8 +24,6 @@
#ifndef _SIS_H_
#define _SIS_H_
-#include <linux/version.h>
-
#include "osdef.h"
#include <video/sisfb.h>
@@ -42,16 +40,6 @@
#define SIS_NEW_CONFIG_COMPAT
#endif /* CONFIG_COMPAT */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
-#define SIS_IOTYPE1 void __iomem
-#define SIS_IOTYPE2 __iomem
-#define SISINITSTATIC static
-#else
-#define SIS_IOTYPE1 unsigned char
-#define SIS_IOTYPE2
-#define SISINITSTATIC
-#endif
-
#undef SISFBDEBUG
#ifdef SISFBDEBUG
@@ -505,8 +493,8 @@ struct sis_video_info {
unsigned long UMAsize, LFBsize;
- SIS_IOTYPE1 *video_vbase;
- SIS_IOTYPE1 *mmio_vbase;
+ void __iomem *video_vbase;
+ void __iomem *mmio_vbase;
unsigned char *bios_abase;
@@ -533,8 +521,8 @@ struct sis_video_info {
int sisfb_nocrt2rate;
u32 heapstart; /* offset */
- SIS_IOTYPE1 *sisfb_heap_start; /* address */
- SIS_IOTYPE1 *sisfb_heap_end; /* address */
+ void __iomem *sisfb_heap_start; /* address */
+ void __iomem *sisfb_heap_end; /* address */
u32 sisfb_heap_size;
int havenoheap;
@@ -612,7 +600,7 @@ struct sis_video_info {
u8 detectedpdca;
u8 detectedlcda;
- SIS_IOTYPE1 *hwcursor_vbase;
+ void __iomem *hwcursor_vbase;
int chronteltype;
int tvxpos, tvypos;
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 7addf91d2fe..ceb434c95c0 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -28,7 +28,6 @@
* for more information and updates)
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b9343844cd1..346d6458cf7 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -33,7 +33,6 @@
*
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -41,13 +40,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
-#include <linux/tty.h>
-#else
#include <linux/screen_info.h>
-#endif
-
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/selection.h>
@@ -1167,11 +1160,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
unsigned short modeno = ivideo->mode_no;
/* >=2.6.12's fbcon clears the screen anyway */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
- if(!clrscrn) modeno |= 0x80;
-#else
modeno |= 0x80;
-#endif
outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -1436,11 +1425,8 @@ sisfb_set_par(struct fb_info *info)
if((err = sisfb_do_set_var(&info->var, 1, info)))
return err;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
- sisfb_get_fix(&info->fix, info->currcon, info);
-#else
sisfb_get_fix(&info->fix, -1, info);
-#endif
+
return 0;
}
@@ -1676,14 +1662,8 @@ sisfb_blank(int blank, struct fb_info *info)
/* ----------- FBDev related routines for all series ---------- */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
-#else
-static int sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
-#endif
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
struct sis_memreq sismemreq;
@@ -3986,8 +3966,7 @@ sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_comm
}
#ifndef MODULE
-SISINITSTATIC int __init
-sisfb_setup(char *options)
+static int __init sisfb_setup(char *options)
{
char *this_opt;
@@ -4086,9 +4065,9 @@ sisfb_setup(char *options)
#endif
static int __devinit
-sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
{
- SIS_IOTYPE1 *rom;
+ void __iomem *rom;
int romptr;
if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
@@ -4117,10 +4096,9 @@ static unsigned char * __devinit
sisfb_find_rom(struct pci_dev *pdev)
{
struct sis_video_info *ivideo = pci_get_drvdata(pdev);
- SIS_IOTYPE1 *rom_base;
+ void __iomem *rom_base;
unsigned char *myrombase = NULL;
u32 temp;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
size_t romsize;
/* First, try the official pci ROM functions (except
@@ -4151,7 +4129,6 @@ sisfb_find_rom(struct pci_dev *pdev)
}
if(myrombase) return myrombase;
-#endif
/* Otherwise do it the conventional way. */
@@ -4225,7 +4202,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
static int __devinit
sisfb_post_300_buswidth(struct sis_video_info *ivideo)
{
- SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+ void __iomem *FBAddress = ivideo->video_vbase;
unsigned short temp;
unsigned char reg;
int i, j;
@@ -4273,7 +4250,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
int PseudoRankCapacity, int PseudoAdrPinCount,
unsigned int mapsize)
{
- SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+ void __iomem *FBAddr = ivideo->video_vbase;
unsigned short sr14;
unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
@@ -5829,7 +5806,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->engineok = 0;
ivideo->sisfb_was_boot_device = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+
if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
if(ivideo->sisvga_enabled)
ivideo->sisfb_was_boot_device = 1;
@@ -5840,7 +5817,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
"as the primary VGA device\n");
}
}
-#endif
ivideo->sisfb_parm_mem = sisfb_parm_mem;
ivideo->sisfb_accel = sisfb_accel;
@@ -6010,7 +5986,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->modeprechange = reg & 0x7f;
} else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
- unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
+ unsigned char __iomem *tt = ioremap(0x400, 0x100);
if(tt) {
ivideo->modeprechange = readb(tt + 0x49);
iounmap(tt);
@@ -6503,7 +6479,7 @@ static struct pci_driver sisfb_driver = {
.remove = __devexit_p(sisfb_remove)
};
-SISINITSTATIC int __init sisfb_init(void)
+static int __init sisfb_init(void)
{
#ifndef MODULE
char *options = NULL;
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 3e3b7fa05d6..9540e977270 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -665,11 +665,11 @@ static struct _customttable {
/* Interface used by the world */
#ifndef MODULE
-SISINITSTATIC int sisfb_setup(char *options);
+static int sisfb_setup(char *options);
#endif
/* Interface to the low level console driver */
-SISINITSTATIC int sisfb_init(void);
+static int sisfb_init(void);
/* fbdev routines */
static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index b532fbd2b04..81a22eaabfd 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -53,10 +53,6 @@
#ifndef _VGATYPES_H_
#define _VGATYPES_H_
-#ifdef SIS_LINUX_KERNEL
-#include <linux/version.h>
-#endif
-
#define SISIOMEMTYPE
#ifdef SIS_LINUX_KERNEL
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 62321458f71..df5336561d1 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -675,13 +675,13 @@ static struct fb_ops xxxfb_ops = {
* Initialization
*/
-/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
static int __devinit xxxfb_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
struct fb_info *info;
struct xxx_par *par;
- struct device* device = &dev->dev; /* for pci drivers */
+ struct device *device = &dev->dev; /* or &pdev->dev */
int cmap_len, retval;
/*
@@ -824,18 +824,18 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
return -EINVAL;
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
info->fix.id);
- pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+ pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
return 0;
}
/*
* Cleanup
*/
-/* static void __devexit xxxfb_remove(struct device *device) */
+/* static void __devexit xxxfb_remove(struct platform_device *pdev) */
static void __devexit xxxfb_remove(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- /* or dev_get_drvdata(device); */
+ /* or platform_get_drvdata(pdev); */
if (info) {
unregister_framebuffer(info);
@@ -961,18 +961,17 @@ static int xxxfb_resume(struct platform_dev *dev)
#define xxxfb_resume NULL
#endif /* CONFIG_PM */
-static struct device_driver xxxfb_driver = {
- .name = "xxxfb",
- .bus = &platform_bus_type,
+static struct platform_device_driver xxxfb_driver = {
.probe = xxxfb_probe,
.remove = xxxfb_remove,
.suspend = xxxfb_suspend, /* optional but recommended */
.resume = xxxfb_resume, /* optional but recommended */
+ .driver = {
+ .name = "xxxfb",
+ },
};
-static struct platform_device xxxfb_device = {
- .name = "xxxfb",
-};
+static struct platform_device *xxxfb_device;
#ifndef MODULE
/*
@@ -1002,12 +1001,16 @@ static int __init xxxfb_init(void)
return -ENODEV;
xxxfb_setup(option);
#endif
- ret = driver_register(&xxxfb_driver);
+ ret = platform_driver_register(&xxxfb_driver);
if (!ret) {
- ret = platform_device_register(&xxxfb_device);
- if (ret)
- driver_unregister(&xxxfb_driver);
+ xxxfb_device = platform_device_register_simple("xxxfb", 0,
+ NULL, 0);
+
+ if (IS_ERR(xxxfb_device)) {
+ platform_driver_unregister(&xxxfb_driver);
+ ret = PTR_ERR(xxxfb_device);
+ }
}
return ret;
@@ -1015,8 +1018,8 @@ static int __init xxxfb_init(void)
static void __exit xxxfb_exit(void)
{
- platform_device_unregister(&xxxfb_device);
- driver_unregister(&xxxfb_driver);
+ platform_device_unregister(xxxfb_device);
+ platform_driver_unregister(&xxxfb_driver);
}
#endif /* CONFIG_PCI */
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 15d4a768b1f..f94ae84a58c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -48,10 +48,15 @@ enum sm501_controller {
HEAD_PANEL = 1,
};
-/* SM501 memory address */
+/* SM501 memory address.
+ *
+ * This structure is used to track memory usage within the SM501 framebuffer
+ * allocation. The sm_addr field is stored as an offset as it is often used
+ * against both the physical and mapped addresses.
+ */
struct sm501_mem {
unsigned long size;
- unsigned long sm_addr;
+ unsigned long sm_addr; /* offset from base of sm501 fb. */
void __iomem *k_addr;
};
@@ -142,31 +147,68 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
unsigned int why, size_t size)
{
- unsigned int ptr = 0;
+ struct sm501fb_par *par;
+ struct fb_info *fbi;
+ unsigned int ptr;
+ unsigned int end;
switch (why) {
case SM501_MEMF_CURSOR:
ptr = inf->fbmem_len - size;
- inf->fbmem_len = ptr;
+ inf->fbmem_len = ptr; /* adjust available memory. */
break;
case SM501_MEMF_PANEL:
ptr = inf->fbmem_len - size;
- if (ptr < inf->fb[0]->fix.smem_len)
+ fbi = inf->fb[HEAD_CRT];
+
+ /* round down, some programs such as directfb do not draw
+ * 0,0 correctly unless the start is aligned to a page start.
+ */
+
+ if (ptr > 0)
+ ptr &= ~(PAGE_SIZE - 1);
+
+ if (fbi && ptr < fbi->fix.smem_len)
+ return -ENOMEM;
+
+ if (ptr < 0)
return -ENOMEM;
break;
case SM501_MEMF_CRT:
ptr = 0;
+
+ /* check to see if we have panel memory allocated
+ * which would put an limit on available memory. */
+
+ fbi = inf->fb[HEAD_PANEL];
+ if (fbi) {
+ par = fbi->par;
+ end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
+ } else
+ end = inf->fbmem_len;
+
+ if ((ptr + size) > end)
+ return -ENOMEM;
+
break;
case SM501_MEMF_ACCEL:
- ptr = inf->fb[0]->fix.smem_len;
+ fbi = inf->fb[HEAD_CRT];
+ ptr = fbi ? fbi->fix.smem_len : 0;
+
+ fbi = inf->fb[HEAD_PANEL];
+ if (fbi) {
+ par = fbi->par;
+ end = par->screen.sm_addr;
+ } else
+ end = inf->fbmem_len;
- if ((ptr + size) >
- (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+ if ((ptr + size) > end)
return -ENOMEM;
+
break;
default:
@@ -663,15 +705,25 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
sm501fb_sync_regs(fbi);
mdelay(10);
+ /* VBIASEN */
+
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
- control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+ control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+ else
+ control |= SM501_DC_PANEL_CONTROL_BIAS;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
- control |= SM501_DC_PANEL_CONTROL_FPEN;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+ control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+ else
+ control |= SM501_DC_PANEL_CONTROL_FPEN;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -679,14 +731,22 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
/* disable panel power */
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
- control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+ control |= SM501_DC_PANEL_CONTROL_FPEN;
+ else
+ control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
- control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+ if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+ control |= SM501_DC_PANEL_CONTROL_BIAS;
+ else
+ control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+
writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -1210,39 +1270,6 @@ static struct fb_ops sm501fb_ops_pnl = {
.fb_imageblit = cfb_imageblit,
};
-/* sm501fb_info_alloc
- *
- * creates and initialises an sm501fb_info structure
-*/
-
-static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
- struct fb_info *fbinfo_pnl)
-{
- struct sm501fb_info *info;
- struct sm501fb_par *par;
-
- info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
- if (info) {
- /* set the references back */
-
- par = fbinfo_crt->par;
- par->info = info;
- par->head = HEAD_CRT;
- fbinfo_crt->pseudo_palette = &par->pseudo_palette;
-
- par = fbinfo_pnl->par;
- par->info = info;
- par->head = HEAD_PANEL;
- fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
-
- /* store the two fbs into our info */
- info->fb[HEAD_CRT] = fbinfo_crt;
- info->fb[HEAD_PANEL] = fbinfo_pnl;
- }
-
- return info;
-}
-
/* sm501_init_cursor
*
* initialise hw cursor parameters
@@ -1250,10 +1277,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
{
- struct sm501fb_par *par = fbi->par;
- struct sm501fb_info *info = par->info;
+ struct sm501fb_par *par;
+ struct sm501fb_info *info;
int ret;
+ if (fbi == NULL)
+ return 0;
+
+ par = fbi->par;
+ info = par->info;
+
par->cursor_regs = info->regs + reg_base;
ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1281,13 +1314,10 @@ static int sm501fb_start(struct sm501fb_info *info,
struct platform_device *pdev)
{
struct resource *res;
- struct device *dev;
+ struct device *dev = &pdev->dev;
int k;
int ret;
- info->dev = dev = &pdev->dev;
- platform_set_drvdata(pdev, info);
-
info->irq = ret = platform_get_irq(pdev, 0);
if (ret < 0) {
/* we currently do not use the IRQ */
@@ -1390,11 +1420,6 @@ static void sm501fb_stop(struct sm501fb_info *info)
kfree(info->regs_res);
}
-static void sm501fb_info_release(struct sm501fb_info *info)
-{
- kfree(info);
-}
-
static int sm501fb_init_fb(struct fb_info *fb,
enum sm501_controller head,
const char *fbname)
@@ -1539,36 +1564,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
static char driver_name_crt[] = "sm501fb-crt";
static char driver_name_pnl[] = "sm501fb-panel";
-static int __init sm501fb_probe(struct platform_device *pdev)
+static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
+ enum sm501_controller head)
{
- struct sm501fb_info *info;
- struct device *dev = &pdev->dev;
- struct fb_info *fbinfo_crt;
- struct fb_info *fbinfo_pnl;
- int ret;
+ unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
+ struct sm501_platdata_fbsub *pd;
+ struct sm501fb_par *par;
+ struct fb_info *fbi;
- /* allocate our framebuffers */
+ pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
+
+ /* Do not initialise if we've not been given any platform data */
+ if (pd == NULL) {
+ dev_info(info->dev, "no data for fb %s (disabled)\n", name);
+ return 0;
+ }
- fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
- if (fbinfo_crt == NULL) {
- dev_err(dev, "cannot allocate crt framebuffer\n");
+ fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
+ if (fbi == NULL) {
+ dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
return -ENOMEM;
}
- fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
- if (fbinfo_pnl == NULL) {
- dev_err(dev, "cannot allocate panel framebuffer\n");
- ret = -ENOMEM;
- goto fbinfo_crt_alloc_fail;
+ par = fbi->par;
+ par->info = info;
+ par->head = head;
+ fbi->pseudo_palette = &par->pseudo_palette;
+
+ info->fb[head] = fbi;
+
+ return 0;
+}
+
+/* Free up anything allocated by sm501fb_init_fb */
+
+static void sm501_free_init_fb(struct sm501fb_info *info,
+ enum sm501_controller head)
+{
+ struct fb_info *fbi = info->fb[head];
+
+ fb_dealloc_cmap(&fbi->cmap);
+}
+
+static int __devinit sm501fb_start_one(struct sm501fb_info *info,
+ enum sm501_controller head,
+ const char *drvname)
+{
+ struct fb_info *fbi = info->fb[head];
+ int ret;
+
+ if (!fbi)
+ return 0;
+
+ ret = sm501fb_init_fb(info->fb[head], head, drvname);
+ if (ret) {
+ dev_err(info->dev, "cannot initialise fb %s\n", drvname);
+ return ret;
+ }
+
+ ret = register_framebuffer(info->fb[head]);
+ if (ret) {
+ dev_err(info->dev, "failed to register fb %s\n", drvname);
+ sm501_free_init_fb(info, head);
+ return ret;
}
- info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
- if (info == NULL) {
- dev_err(dev, "cannot allocate par\n");
- ret = -ENOMEM;
- goto sm501fb_alloc_fail;
+ dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
+
+ return 0;
+}
+
+static int __devinit sm501fb_probe(struct platform_device *pdev)
+{
+ struct sm501fb_info *info;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ /* allocate our framebuffers */
+
+ info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+ if (!info) {
+ dev_err(dev, "failed to allocate state\n");
+ return -ENOMEM;
}
+ info->dev = dev = &pdev->dev;
+ platform_set_drvdata(pdev, info);
+
if (dev->parent->platform_data) {
struct sm501_platdata *pd = dev->parent->platform_data;
info->pdata = pd->fb;
@@ -1579,90 +1661,88 @@ static int __init sm501fb_probe(struct platform_device *pdev)
info->pdata = &sm501fb_def_pdata;
}
- /* start the framebuffers */
+ /* probe for the presence of each panel */
- ret = sm501fb_start(info, pdev);
- if (ret) {
- dev_err(dev, "cannot initialise SM501\n");
- goto sm501fb_start_fail;
+ ret = sm501fb_probe_one(info, HEAD_CRT);
+ if (ret < 0) {
+ dev_err(dev, "failed to probe CRT\n");
+ goto err_alloc;
}
- /* CRT framebuffer setup */
+ ret = sm501fb_probe_one(info, HEAD_PANEL);
+ if (ret < 0) {
+ dev_err(dev, "failed to probe PANEL\n");
+ goto err_probed_crt;
+ }
- ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
- if (ret) {
- dev_err(dev, "cannot initialise CRT fb\n");
- goto sm501fb_start_fail;
+ if (info->fb[HEAD_PANEL] == NULL &&
+ info->fb[HEAD_CRT] == NULL) {
+ dev_err(dev, "no framebuffers found\n");
+ goto err_alloc;
}
- /* Panel framebuffer setup */
+ /* get the resources for both of the framebuffers */
- ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+ ret = sm501fb_start(info, pdev);
if (ret) {
- dev_err(dev, "cannot initialise Panel fb\n");
- goto sm501fb_start_fail;
+ dev_err(dev, "cannot initialise SM501\n");
+ goto err_probed_panel;
}
- /* register framebuffers */
-
- ret = register_framebuffer(fbinfo_crt);
- if (ret < 0) {
- dev_err(dev, "failed to register CRT fb (%d)\n", ret);
- goto register_crt_fail;
+ ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
+ if (ret) {
+ dev_err(dev, "failed to start CRT\n");
+ goto err_started;
}
- ret = register_framebuffer(fbinfo_pnl);
- if (ret < 0) {
- dev_err(dev, "failed to register panel fb (%d)\n", ret);
- goto register_pnl_fail;
+ ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
+ if (ret) {
+ dev_err(dev, "failed to start Panel\n");
+ goto err_started_crt;
}
- dev_info(dev, "fb%d: %s frame buffer device\n",
- fbinfo_crt->node, fbinfo_crt->fix.id);
-
- dev_info(dev, "fb%d: %s frame buffer device\n",
- fbinfo_pnl->node, fbinfo_pnl->fix.id);
-
/* create device files */
ret = device_create_file(dev, &dev_attr_crt_src);
if (ret)
- goto crtsrc_fail;
+ goto err_started_panel;
ret = device_create_file(dev, &dev_attr_fbregs_pnl);
if (ret)
- goto fbregs_pnl_fail;
+ goto err_attached_crtsrc_file;
ret = device_create_file(dev, &dev_attr_fbregs_crt);
if (ret)
- goto fbregs_crt_fail;
+ goto err_attached_pnlregs_file;
/* we registered, return ok */
return 0;
- fbregs_crt_fail:
+err_attached_pnlregs_file:
device_remove_file(dev, &dev_attr_fbregs_pnl);
- fbregs_pnl_fail:
+err_attached_crtsrc_file:
device_remove_file(dev, &dev_attr_crt_src);
- crtsrc_fail:
- unregister_framebuffer(fbinfo_pnl);
+err_started_panel:
+ unregister_framebuffer(info->fb[HEAD_PANEL]);
+ sm501_free_init_fb(info, HEAD_PANEL);
- register_pnl_fail:
- unregister_framebuffer(fbinfo_crt);
+err_started_crt:
+ unregister_framebuffer(info->fb[HEAD_CRT]);
+ sm501_free_init_fb(info, HEAD_CRT);
- register_crt_fail:
+err_started:
sm501fb_stop(info);
- sm501fb_start_fail:
- sm501fb_info_release(info);
+err_probed_panel:
+ framebuffer_release(info->fb[HEAD_PANEL]);
- sm501fb_alloc_fail:
- framebuffer_release(fbinfo_pnl);
+err_probed_crt:
+ framebuffer_release(info->fb[HEAD_CRT]);
- fbinfo_crt_alloc_fail:
- framebuffer_release(fbinfo_crt);
+err_alloc:
+ kfree(info);
return ret;
}
@@ -1681,11 +1761,14 @@ static int sm501fb_remove(struct platform_device *pdev)
device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
device_remove_file(&pdev->dev, &dev_attr_crt_src);
+ sm501_free_init_fb(info, HEAD_CRT);
+ sm501_free_init_fb(info, HEAD_PANEL);
+
unregister_framebuffer(fbinfo_crt);
unregister_framebuffer(fbinfo_pnl);
sm501fb_stop(info);
- sm501fb_info_release(info);
+ kfree(info);
framebuffer_release(fbinfo_pnl);
framebuffer_release(fbinfo_crt);
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ea9f19d2559..77aafcfae03 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -836,16 +836,12 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
struct tdfx_par *par = info->par;
u32 addr = var->yoffset * info->fix.line_length;
- if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
- return -EINVAL;
- if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
+ if (nopan || var->xoffset)
return -EINVAL;
banshee_make_room(par, 1);
tdfx_outl(par, VIDDESKSTART, addr);
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
return 0;
}
@@ -1426,6 +1422,8 @@ MODULE_LICENSE("GPL");
module_param(hwcursor, int, 0644);
MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
"(1=enable, 0=disable, default=1)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index beefab2992c..479b2e79ad6 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1,5 +1,5 @@
/*
- * Frame buffer driver for Trident Blade and Image series
+ * Frame buffer driver for Trident TGUI, Blade and Image series
*
* Copyright 2001, 2002 - Jani Monoses <jani@iv.ro>
*
@@ -13,7 +13,6 @@
* code, suggestions
* TODO:
* timing value tweaking so it looks good on every monitor in every mode
- * TGUI acceleration
*/
#include <linux/module.h>
@@ -22,25 +21,26 @@
#include <linux/pci.h>
#include <linux/delay.h>
+#include <video/vga.h>
#include <video/trident.h>
-#define VERSION "0.7.8-NEWAPI"
-
struct tridentfb_par {
void __iomem *io_virt; /* iospace virtual memory address */
+ u32 pseudo_pal[16];
+ int chip_id;
+ int flatpanel;
+ void (*init_accel) (struct tridentfb_par *, int, int);
+ void (*wait_engine) (struct tridentfb_par *);
+ void (*fill_rect)
+ (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+ void (*copy_rect)
+ (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
+ void (*image_blit)
+ (struct tridentfb_par *par, const char*,
+ u32, u32, u32, u32, u32, u32);
+ unsigned char eng_oper; /* engine operation... */
};
-static unsigned char eng_oper; /* engine operation... */
-static struct fb_ops tridentfb_ops;
-
-static struct tridentfb_par default_par;
-
-/* FIXME:kmalloc these 3 instead */
-static struct fb_info fb_info;
-static u32 pseudo_pal[16];
-
-static struct fb_var_screeninfo default_var;
-
static struct fb_fix_screeninfo tridentfb_fix = {
.id = "Trident",
.type = FB_TYPE_PACKED_PIXELS,
@@ -49,27 +49,22 @@ static struct fb_fix_screeninfo tridentfb_fix = {
.accel = FB_ACCEL_NONE,
};
-static int chip_id;
-
-static int defaultaccel;
-static int displaytype;
-
/* defaults which are normally overriden by user values */
/* video mode */
-static char *mode_option __devinitdata = "640x480";
-static int bpp = 8;
+static char *mode_option __devinitdata = "640x480-8@60";
+static int bpp __devinitdata = 8;
-static int noaccel;
+static int noaccel __devinitdata;
static int center;
static int stretch;
-static int fp;
-static int crt;
+static int fp __devinitdata;
+static int crt __devinitdata;
-static int memsize;
-static int memdiff;
+static int memsize __devinitdata;
+static int memdiff __devinitdata;
static int nativex;
module_param(mode_option, charp, 0);
@@ -84,25 +79,53 @@ module_param(memsize, int, 0);
module_param(memdiff, int, 0);
module_param(nativex, int, 0);
module_param(fp, int, 0);
+MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
module_param(crt, int, 0);
+MODULE_PARM_DESC(crt, "Define if CRT is connected");
+
+static inline int is_oldclock(int id)
+{
+ return (id == TGUI9440) ||
+ (id == TGUI9660) ||
+ (id == CYBER9320);
+}
+
+static inline int is_oldprotect(int id)
+{
+ return is_oldclock(id) ||
+ (id == PROVIDIA9685) ||
+ (id == CYBER9382) ||
+ (id == CYBER9385);
+}
+
+static inline int is_blade(int id)
+{
+ return (id == BLADE3D) ||
+ (id == CYBERBLADEE4) ||
+ (id == CYBERBLADEi7) ||
+ (id == CYBERBLADEi7D) ||
+ (id == CYBERBLADEi1) ||
+ (id == CYBERBLADEi1D) ||
+ (id == CYBERBLADEAi1) ||
+ (id == CYBERBLADEAi1D);
+}
-static int chip3D;
-static int chipcyber;
+static inline int is_xp(int id)
+{
+ return (id == CYBERBLADEXPAi1) ||
+ (id == CYBERBLADEXPm8) ||
+ (id == CYBERBLADEXPm16);
+}
-static int is3Dchip(int id)
+static inline int is3Dchip(int id)
{
- return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
- (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
+ return is_blade(id) || is_xp(id) ||
(id == CYBER9397) || (id == CYBER9397DVD) ||
(id == CYBER9520) || (id == CYBER9525DVD) ||
- (id == IMAGE975) || (id == IMAGE985) ||
- (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
- (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
- (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
- (id == CYBERBLADEXPAi1));
+ (id == IMAGE975) || (id == IMAGE985);
}
-static int iscyber(int id)
+static inline int iscyber(int id)
{
switch (id) {
case CYBER9388:
@@ -122,12 +145,7 @@ static int iscyber(int id)
return 1;
case CYBER9320:
- case TGUI9660:
- case IMAGE975:
- case IMAGE985:
- case BLADE3D:
case CYBERBLADEi7: /* VIA MPV4 integrated version */
-
default:
/* case CYBERBLDAEXPm8: Strange */
/* case CYBERBLDAEXPm16: Strange */
@@ -135,147 +153,110 @@ static int iscyber(int id)
}
}
-#define CRT 0x3D0 /* CRTC registers offset for color display */
-
-#ifndef TRIDENT_MMIO
- #define TRIDENT_MMIO 1
-#endif
-
-#if TRIDENT_MMIO
- #define t_outb(val, reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
- #define t_inb(reg) readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg)
-#else
- #define t_outb(val, reg) outb(val, reg)
- #define t_inb(reg) inb(reg)
-#endif
+static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
+{
+ fb_writeb(val, p->io_virt + reg);
+}
+static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
+{
+ return fb_readb(p->io_virt + reg);
+}
-static struct accel_switch {
- void (*init_accel) (int, int);
- void (*wait_engine) (void);
- void (*fill_rect) (u32, u32, u32, u32, u32, u32);
- void (*copy_rect) (u32, u32, u32, u32, u32, u32);
-} *acc;
+static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
+{
+ fb_writel(v, par->io_virt + r);
+}
-#define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r)
-#define readmmr(r) readl(((struct tridentfb_par *)fb_info.par)->io_virt + r)
+static inline u32 readmmr(struct tridentfb_par *par, u16 r)
+{
+ return fb_readl(par->io_virt + r);
+}
/*
* Blade specific acceleration.
*/
#define point(x, y) ((y) << 16 | (x))
-#define STA 0x2120
-#define CMD 0x2144
-#define ROP 0x2148
-#define CLR 0x2160
-#define SR1 0x2100
-#define SR2 0x2104
-#define DR1 0x2108
-#define DR2 0x210C
-
-#define ROP_S 0xCC
-
-static void blade_init_accel(int pitch, int bpp)
+
+static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
int v1 = (pitch >> 3) << 20;
- int tmp = 0, v2;
- switch (bpp) {
- case 8:
- tmp = 0;
- break;
- case 15:
- tmp = 5;
- break;
- case 16:
- tmp = 1;
- break;
- case 24:
- case 32:
- tmp = 2;
- break;
- }
- v2 = v1 | (tmp << 29);
- writemmr(0x21C0, v2);
- writemmr(0x21C4, v2);
- writemmr(0x21B8, v2);
- writemmr(0x21BC, v2);
- writemmr(0x21D0, v1);
- writemmr(0x21D4, v1);
- writemmr(0x21C8, v1);
- writemmr(0x21CC, v1);
- writemmr(0x216C, 0);
+ int tmp = bpp == 24 ? 2 : (bpp >> 4);
+ int v2 = v1 | (tmp << 29);
+
+ writemmr(par, 0x21C0, v2);
+ writemmr(par, 0x21C4, v2);
+ writemmr(par, 0x21B8, v2);
+ writemmr(par, 0x21BC, v2);
+ writemmr(par, 0x21D0, v1);
+ writemmr(par, 0x21D4, v1);
+ writemmr(par, 0x21C8, v1);
+ writemmr(par, 0x21CC, v1);
+ writemmr(par, 0x216C, 0);
}
-static void blade_wait_engine(void)
+static void blade_wait_engine(struct tridentfb_par *par)
{
- while (readmmr(STA) & 0xFA800000) ;
+ while (readmmr(par, STATUS) & 0xFA800000)
+ cpu_relax();
}
-static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void blade_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(CLR, c);
- writemmr(ROP, rop ? 0x66 : ROP_S);
- writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+ writemmr(par, COLOR, c);
+ writemmr(par, ROP, rop ? ROP_X : ROP_S);
+ writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
- writemmr(DR1, point(x, y));
- writemmr(DR2, point(x + w - 1, y + h - 1));
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
}
-static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void blade_image_blit(struct tridentfb_par *par, const char *data,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
+{
+ unsigned size = ((w + 31) >> 5) * h;
+
+ writemmr(par, COLOR, c);
+ writemmr(par, BGCOLOR, b);
+ writemmr(par, CMD, 0xa0000000 | 3 << 19);
+
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
+
+ memcpy(par->io_virt + 0x10000, data, 4 * size);
+}
+
+static void blade_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- u32 s1, s2, d1, d2;
int direction = 2;
- s1 = point(x1, y1);
- s2 = point(x1 + w - 1, y1 + h - 1);
- d1 = point(x2, y2);
- d2 = point(x2 + w - 1, y2 + h - 1);
+ u32 s1 = point(x1, y1);
+ u32 s2 = point(x1 + w - 1, y1 + h - 1);
+ u32 d1 = point(x2, y2);
+ u32 d2 = point(x2 + w - 1, y2 + h - 1);
if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
direction = 0;
- writemmr(ROP, ROP_S);
- writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
+ writemmr(par, ROP, ROP_S);
+ writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
- writemmr(SR1, direction ? s2 : s1);
- writemmr(SR2, direction ? s1 : s2);
- writemmr(DR1, direction ? d2 : d1);
- writemmr(DR2, direction ? d1 : d2);
+ writemmr(par, SRC1, direction ? s2 : s1);
+ writemmr(par, SRC2, direction ? s1 : s2);
+ writemmr(par, DST1, direction ? d2 : d1);
+ writemmr(par, DST2, direction ? d1 : d2);
}
-static struct accel_switch accel_blade = {
- blade_init_accel,
- blade_wait_engine,
- blade_fill_rect,
- blade_copy_rect,
-};
-
/*
* BladeXP specific acceleration functions
*/
-#define ROP_P 0xF0
-#define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff))
-
-static void xp_init_accel(int pitch, int bpp)
+static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
- int tmp = 0, v1;
- unsigned char x = 0;
-
- switch (bpp) {
- case 8:
- x = 0;
- break;
- case 16:
- x = 1;
- break;
- case 24:
- x = 3;
- break;
- case 32:
- x = 2;
- break;
- }
+ unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+ int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
switch (pitch << (bpp >> 3)) {
case 8192:
@@ -293,42 +274,21 @@ static void xp_init_accel(int pitch, int bpp)
break;
}
- t_outb(x, 0x2125);
-
- eng_oper = x | 0x40;
-
- switch (bpp) {
- case 8:
- tmp = 18;
- break;
- case 15:
- case 16:
- tmp = 19;
- break;
- case 24:
- case 32:
- tmp = 20;
- break;
- }
+ t_outb(par, x, 0x2125);
- v1 = pitch << tmp;
+ par->eng_oper = x | 0x40;
- writemmr(0x2154, v1);
- writemmr(0x2150, v1);
- t_outb(3, 0x2126);
+ writemmr(par, 0x2154, v1);
+ writemmr(par, 0x2150, v1);
+ t_outb(par, 3, 0x2126);
}
-static void xp_wait_engine(void)
+static void xp_wait_engine(struct tridentfb_par *par)
{
- int busy;
- int count, timeout;
-
- count = 0;
- timeout = 0;
- for (;;) {
- busy = t_inb(STA) & 0x80;
- if (busy != 0x80)
- return;
+ int count = 0;
+ int timeout = 0;
+
+ while (t_inb(par, STATUS) & 0x80) {
count++;
if (count == 10000000) {
/* Timeout */
@@ -336,30 +296,31 @@ static void xp_wait_engine(void)
timeout++;
if (timeout == 8) {
/* Reset engine */
- t_outb(0x00, 0x2120);
+ t_outb(par, 0x00, STATUS);
return;
}
}
+ cpu_relax();
}
}
-static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void xp_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2127, ROP_P);
- writemmr(0x2158, c);
- writemmr(0x2128, 0x4000);
- writemmr(0x2140, masked_point(h, w));
- writemmr(0x2138, masked_point(y, x));
- t_outb(0x01, 0x2124);
- t_outb(eng_oper, 0x2125);
+ writemmr(par, 0x2127, ROP_P);
+ writemmr(par, 0x2158, c);
+ writemmr(par, DRAWFL, 0x4000);
+ writemmr(par, OLDDIM, point(h, w));
+ writemmr(par, OLDDST, point(y, x));
+ t_outb(par, 0x01, OLDCMD);
+ t_outb(par, par->eng_oper, 0x2125);
}
-static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void xp_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- int direction;
u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
-
- direction = 0x0004;
+ int direction = 0x0004;
if ((x1 < x2) && (y1 == y2)) {
direction |= 0x0200;
@@ -379,103 +340,152 @@ static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
y2_tmp = y2;
}
- writemmr(0x2128, direction);
- t_outb(ROP_S, 0x2127);
- writemmr(0x213C, masked_point(y1_tmp, x1_tmp));
- writemmr(0x2138, masked_point(y2_tmp, x2_tmp));
- writemmr(0x2140, masked_point(h, w));
- t_outb(0x01, 0x2124);
+ writemmr(par, DRAWFL, direction);
+ t_outb(par, ROP_S, 0x2127);
+ writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
+ writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
+ writemmr(par, OLDDIM, point(h, w));
+ t_outb(par, 0x01, OLDCMD);
}
-static struct accel_switch accel_xp = {
- xp_init_accel,
- xp_wait_engine,
- xp_fill_rect,
- xp_copy_rect,
-};
-
/*
* Image specific acceleration functions
*/
-static void image_init_accel(int pitch, int bpp)
+static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
{
- int tmp = 0;
- switch (bpp) {
- case 8:
- tmp = 0;
- break;
- case 15:
- tmp = 5;
- break;
- case 16:
- tmp = 1;
- break;
- case 24:
- case 32:
- tmp = 2;
- break;
- }
- writemmr(0x2120, 0xF0000000);
- writemmr(0x2120, 0x40000000 | tmp);
- writemmr(0x2120, 0x80000000);
- writemmr(0x2144, 0x00000000);
- writemmr(0x2148, 0x00000000);
- writemmr(0x2150, 0x00000000);
- writemmr(0x2154, 0x00000000);
- writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch);
- writemmr(0x216C, 0x00000000);
- writemmr(0x2170, 0x00000000);
- writemmr(0x217C, 0x00000000);
- writemmr(0x2120, 0x10000000);
- writemmr(0x2130, (2047 << 16) | 2047);
+ int tmp = bpp == 24 ? 2: (bpp >> 4);
+
+ writemmr(par, 0x2120, 0xF0000000);
+ writemmr(par, 0x2120, 0x40000000 | tmp);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2144, 0x00000000);
+ writemmr(par, 0x2148, 0x00000000);
+ writemmr(par, 0x2150, 0x00000000);
+ writemmr(par, 0x2154, 0x00000000);
+ writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
+ writemmr(par, 0x216C, 0x00000000);
+ writemmr(par, 0x2170, 0x00000000);
+ writemmr(par, 0x217C, 0x00000000);
+ writemmr(par, 0x2120, 0x10000000);
+ writemmr(par, 0x2130, (2047 << 16) | 2047);
}
-static void image_wait_engine(void)
+static void image_wait_engine(struct tridentfb_par *par)
{
- while (readmmr(0x2164) & 0xF0000000) ;
+ while (readmmr(par, 0x2164) & 0xF0000000)
+ cpu_relax();
}
-static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+static void image_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
{
- writemmr(0x2120, 0x80000000);
- writemmr(0x2120, 0x90000000 | ROP_S);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2120, 0x90000000 | ROP_S);
- writemmr(0x2144, c);
+ writemmr(par, 0x2144, c);
- writemmr(DR1, point(x, y));
- writemmr(DR2, point(x + w - 1, y + h - 1));
+ writemmr(par, DST1, point(x, y));
+ writemmr(par, DST2, point(x + w - 1, y + h - 1));
- writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
+ writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
}
-static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+static void image_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
{
- u32 s1, s2, d1, d2;
- int direction = 2;
- s1 = point(x1, y1);
- s2 = point(x1 + w - 1, y1 + h - 1);
- d1 = point(x2, y2);
- d2 = point(x2 + w - 1, y2 + h - 1);
+ int direction = 0x4;
+ u32 s1 = point(x1, y1);
+ u32 s2 = point(x1 + w - 1, y1 + h - 1);
+ u32 d1 = point(x2, y2);
+ u32 d2 = point(x2 + w - 1, y2 + h - 1);
if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
direction = 0;
- writemmr(0x2120, 0x80000000);
- writemmr(0x2120, 0x90000000 | ROP_S);
+ writemmr(par, 0x2120, 0x80000000);
+ writemmr(par, 0x2120, 0x90000000 | ROP_S);
- writemmr(SR1, direction ? s2 : s1);
- writemmr(SR2, direction ? s1 : s2);
- writemmr(DR1, direction ? d2 : d1);
- writemmr(DR2, direction ? d1 : d2);
- writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
+ writemmr(par, SRC1, direction ? s2 : s1);
+ writemmr(par, SRC2, direction ? s1 : s2);
+ writemmr(par, DST1, direction ? d2 : d1);
+ writemmr(par, DST2, direction ? d1 : d2);
+ writemmr(par, 0x2124,
+ 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
}
-static struct accel_switch accel_image = {
- image_init_accel,
- image_wait_engine,
- image_fill_rect,
- image_copy_rect,
-};
+/*
+ * TGUI 9440/96XX acceleration
+ */
+
+static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
+{
+ unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
+
+ /* disable clipping */
+ writemmr(par, 0x2148, 0);
+ writemmr(par, 0x214C, point(4095, 2047));
+
+ switch ((pitch * bpp) / 8) {
+ case 8192:
+ case 512:
+ x |= 0x00;
+ break;
+ case 1024:
+ x |= 0x04;
+ break;
+ case 2048:
+ x |= 0x08;
+ break;
+ case 4096:
+ x |= 0x0C;
+ break;
+ }
+
+ fb_writew(x, par->io_virt + 0x2122);
+}
+
+static void tgui_fill_rect(struct tridentfb_par *par,
+ u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
+{
+ t_outb(par, ROP_P, 0x2127);
+ writemmr(par, OLDCLR, c);
+ writemmr(par, DRAWFL, 0x4020);
+ writemmr(par, OLDDIM, point(w - 1, h - 1));
+ writemmr(par, OLDDST, point(x, y));
+ t_outb(par, 1, OLDCMD);
+}
+
+static void tgui_copy_rect(struct tridentfb_par *par,
+ u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
+{
+ int flags = 0;
+ u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
+
+ if ((x1 < x2) && (y1 == y2)) {
+ flags |= 0x0200;
+ x1_tmp = x1 + w - 1;
+ x2_tmp = x2 + w - 1;
+ } else {
+ x1_tmp = x1;
+ x2_tmp = x2;
+ }
+
+ if (y1 < y2) {
+ flags |= 0x0100;
+ y1_tmp = y1 + h - 1;
+ y2_tmp = y2 + h - 1;
+ } else {
+ y1_tmp = y1;
+ y2_tmp = y2;
+ }
+
+ writemmr(par, DRAWFL, 0x4 | flags);
+ t_outb(par, ROP_S, 0x2127);
+ writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
+ writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
+ writemmr(par, OLDDIM, point(w - 1, h - 1));
+ t_outb(par, 1, OLDCMD);
+}
/*
* Accel functions called by the upper layers
@@ -484,129 +494,162 @@ static struct accel_switch accel_image = {
static void tridentfb_fillrect(struct fb_info *info,
const struct fb_fillrect *fr)
{
- int bpp = info->var.bits_per_pixel;
- int col = 0;
+ struct tridentfb_par *par = info->par;
+ int col;
- switch (bpp) {
- default:
- case 8:
- col |= fr->color;
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_fillrect(info, fr);
+ return;
+ }
+ if (info->var.bits_per_pixel == 8) {
+ col = fr->color;
col |= col << 8;
col |= col << 16;
- break;
- case 16:
+ } else
col = ((u32 *)(info->pseudo_palette))[fr->color];
- break;
- case 32:
- col = ((u32 *)(info->pseudo_palette))[fr->color];
- break;
+
+ par->wait_engine(par);
+ par->fill_rect(par, fr->dx, fr->dy, fr->width,
+ fr->height, col, fr->rop);
+}
+
+static void tridentfb_imageblit(struct fb_info *info,
+ const struct fb_image *img)
+{
+ struct tridentfb_par *par = info->par;
+ int col, bgcol;
+
+ if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
+ cfb_imageblit(info, img);
+ return;
+ }
+ if (info->var.bits_per_pixel == 8) {
+ col = img->fg_color;
+ col |= col << 8;
+ col |= col << 16;
+ bgcol = img->bg_color;
+ bgcol |= bgcol << 8;
+ bgcol |= bgcol << 16;
+ } else {
+ col = ((u32 *)(info->pseudo_palette))[img->fg_color];
+ bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
}
- acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop);
- acc->wait_engine();
+ par->wait_engine(par);
+ if (par->image_blit)
+ par->image_blit(par, img->data, img->dx, img->dy,
+ img->width, img->height, col, bgcol);
+ else
+ cfb_imageblit(info, img);
}
+
static void tridentfb_copyarea(struct fb_info *info,
const struct fb_copyarea *ca)
{
- acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height);
- acc->wait_engine();
+ struct tridentfb_par *par = info->par;
+
+ if (info->flags & FBINFO_HWACCEL_DISABLED) {
+ cfb_copyarea(info, ca);
+ return;
+ }
+ par->wait_engine(par);
+ par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
+ ca->width, ca->height);
+}
+
+static int tridentfb_sync(struct fb_info *info)
+{
+ struct tridentfb_par *par = info->par;
+
+ if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+ par->wait_engine(par);
+ return 0;
}
-#else /* !CONFIG_FB_TRIDENT_ACCEL */
+#else
#define tridentfb_fillrect cfb_fillrect
#define tridentfb_copyarea cfb_copyarea
+#define tridentfb_imageblit cfb_imageblit
#endif /* CONFIG_FB_TRIDENT_ACCEL */
-
/*
* Hardware access functions
*/
-static inline unsigned char read3X4(int reg)
+static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
{
- struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
- writeb(reg, par->io_virt + CRT + 4);
- return readb(par->io_virt + CRT + 5);
+ return vga_mm_rcrt(par->io_virt, reg);
}
-static inline void write3X4(int reg, unsigned char val)
+static inline void write3X4(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par;
- writeb(reg, par->io_virt + CRT + 4);
- writeb(val, par->io_virt + CRT + 5);
+ vga_mm_wcrt(par->io_virt, reg, val);
}
-static inline unsigned char read3C4(int reg)
+static inline unsigned char read3CE(struct tridentfb_par *par,
+ unsigned char reg)
{
- t_outb(reg, 0x3C4);
- return t_inb(0x3C5);
+ return vga_mm_rgfx(par->io_virt, reg);
}
-static inline void write3C4(int reg, unsigned char val)
+static inline void writeAttr(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- t_outb(reg, 0x3C4);
- t_outb(val, 0x3C5);
+ fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
+ vga_mm_wattr(par->io_virt, reg, val);
}
-static inline unsigned char read3CE(int reg)
+static inline void write3CE(struct tridentfb_par *par, int reg,
+ unsigned char val)
{
- t_outb(reg, 0x3CE);
- return t_inb(0x3CF);
+ vga_mm_wgfx(par->io_virt, reg, val);
}
-static inline void writeAttr(int reg, unsigned char val)
-{
- readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); /* flip-flop to index */
- t_outb(reg, 0x3C0);
- t_outb(val, 0x3C0);
-}
-
-static inline void write3CE(int reg, unsigned char val)
-{
- t_outb(reg, 0x3CE);
- t_outb(val, 0x3CF);
-}
-
-static void enable_mmio(void)
+static void enable_mmio(struct tridentfb_par *par)
{
/* Goto New Mode */
- outb(0x0B, 0x3C4);
- inb(0x3C5);
+ vga_io_rseq(0x0B);
/* Unprotect registers */
- outb(NewMode1, 0x3C4);
- outb(0x80, 0x3C5);
+ vga_io_wseq(NewMode1, 0x80);
+ if (!is_oldprotect(par->chip_id))
+ vga_io_wseq(Protection, 0x92);
/* Enable MMIO */
outb(PCIReg, 0x3D4);
outb(inb(0x3D5) | 0x01, 0x3D5);
}
-static void disable_mmio(void)
+static void disable_mmio(struct tridentfb_par *par)
{
/* Goto New Mode */
- t_outb(0x0B, 0x3C4);
- t_inb(0x3C5);
+ vga_mm_rseq(par->io_virt, 0x0B);
/* Unprotect registers */
- t_outb(NewMode1, 0x3C4);
- t_outb(0x80, 0x3C5);
+ vga_mm_wseq(par->io_virt, NewMode1, 0x80);
+ if (!is_oldprotect(par->chip_id))
+ vga_mm_wseq(par->io_virt, Protection, 0x92);
/* Disable MMIO */
- t_outb(PCIReg, 0x3D4);
- t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
+ t_outb(par, PCIReg, 0x3D4);
+ t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
}
-#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
+static inline void crtc_unlock(struct tridentfb_par *par)
+{
+ write3X4(par, VGA_CRTC_V_SYNC_END,
+ read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
+}
/* Return flat panel's maximum x resolution */
-static int __devinit get_nativex(void)
+static int __devinit get_nativex(struct tridentfb_par *par)
{
int x, y, tmp;
if (nativex)
return nativex;
- tmp = (read3CE(VertStretch) >> 4) & 3;
+ tmp = (read3CE(par, VertStretch) >> 4) & 3;
switch (tmp) {
case 0:
@@ -632,77 +675,92 @@ static int __devinit get_nativex(void)
}
/* Set pitch */
-static void set_lwidth(int width)
+static inline void set_lwidth(struct tridentfb_par *par, int width)
{
- write3X4(Offset, width & 0xFF);
- write3X4(AddColReg,
- (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4));
+ write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
+ write3X4(par, AddColReg,
+ (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
}
/* For resolutions smaller than FP resolution stretch */
-static void screen_stretch(void)
+static void screen_stretch(struct tridentfb_par *par)
{
- if (chip_id != CYBERBLADEXPAi1)
- write3CE(BiosReg, 0);
+ if (par->chip_id != CYBERBLADEXPAi1)
+ write3CE(par, BiosReg, 0);
else
- write3CE(BiosReg, 8);
- write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1);
- write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1);
+ write3CE(par, BiosReg, 8);
+ write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
+ write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
}
/* For resolutions smaller than FP resolution center */
-static void screen_center(void)
+static inline void screen_center(struct tridentfb_par *par)
{
- write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80);
- write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80);
+ write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
+ write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
}
/* Address of first shown pixel in display memory */
-static void set_screen_start(int base)
+static void set_screen_start(struct tridentfb_par *par, int base)
{
- write3X4(StartAddrLow, base & 0xFF);
- write3X4(StartAddrHigh, (base & 0xFF00) >> 8);
- write3X4(CRTCModuleTest,
- (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11));
- write3X4(CRTHiOrd,
- (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));
+ u8 tmp;
+ write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
+ write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
+ tmp = read3X4(par, CRTCModuleTest) & 0xDF;
+ write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
+ tmp = read3X4(par, CRTHiOrd) & 0xF8;
+ write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
}
/* Set dotclock frequency */
-static void set_vclk(unsigned long freq)
+static void set_vclk(struct tridentfb_par *par, unsigned long freq)
{
int m, n, k;
- unsigned long f, fi, d, di;
- unsigned char lo = 0, hi = 0;
+ unsigned long fi, d, di;
+ unsigned char best_m = 0, best_n = 0, best_k = 0;
+ unsigned char hi, lo;
+ unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
d = 20000;
- for (k = 2; k >= 0; k--)
- for (m = 0; m < 63; m++)
- for (n = 0; n < 128; n++) {
+ for (k = shift; k >= 0; k--)
+ for (m = 1; m < 32; m++) {
+ n = ((m + 2) << shift) - 8;
+ for (n = (n < 0 ? 0 : n); n < 122; n++) {
fi = ((14318l * (n + 8)) / (m + 2)) >> k;
- if ((di = abs(fi - freq)) < d) {
+ di = abs(fi - freq);
+ if (di < d || (di == d && k == best_k)) {
d = di;
- f = fi;
- lo = n;
- hi = (k << 6) | m;
+ best_n = n;
+ best_m = m;
+ best_k = k;
}
if (fi > freq)
break;
}
- if (chip3D) {
- write3C4(ClockHigh, hi);
- write3C4(ClockLow, lo);
+ }
+
+ if (is_oldclock(par->chip_id)) {
+ lo = best_n | (best_m << 7);
+ hi = (best_m >> 1) | (best_k << 4);
} else {
- outb(lo, 0x43C8);
- outb(hi, 0x43C9);
+ lo = best_n;
+ hi = best_m | (best_k << 6);
+ }
+
+ if (is3Dchip(par->chip_id)) {
+ vga_mm_wseq(par->io_virt, ClockHigh, hi);
+ vga_mm_wseq(par->io_virt, ClockLow, lo);
+ } else {
+ t_outb(par, lo, 0x43C8);
+ t_outb(par, hi, 0x43C9);
}
debug("VCLK = %X %X\n", hi, lo);
}
/* Set number of lines for flat panels*/
-static void set_number_of_lines(int lines)
+static void set_number_of_lines(struct tridentfb_par *par, int lines)
{
- int tmp = read3CE(CyberEnhance) & 0x8F;
+ int tmp = read3CE(par, CyberEnhance) & 0x8F;
if (lines > 1024)
tmp |= 0x50;
else if (lines > 768)
@@ -711,24 +769,24 @@ static void set_number_of_lines(int lines)
tmp |= 0x20;
else if (lines > 480)
tmp |= 0x10;
- write3CE(CyberEnhance, tmp);
+ write3CE(par, CyberEnhance, tmp);
}
/*
* If we see that FP is active we assume we have one.
- * Otherwise we have a CRT display.User can override.
+ * Otherwise we have a CRT display. User can override.
*/
-static unsigned int __devinit get_displaytype(void)
+static int __devinit is_flatpanel(struct tridentfb_par *par)
{
if (fp)
- return DISPLAY_FP;
- if (crt || !chipcyber)
- return DISPLAY_CRT;
- return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
+ return 1;
+ if (crt || !iscyber(par->chip_id))
+ return 0;
+ return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
}
/* Try detecting the video memory size */
-static unsigned int __devinit get_memsize(void)
+static unsigned int __devinit get_memsize(struct tridentfb_par *par)
{
unsigned char tmp, tmp2;
unsigned int k;
@@ -737,12 +795,12 @@ static unsigned int __devinit get_memsize(void)
if (memsize)
k = memsize * Kb;
else
- switch (chip_id) {
+ switch (par->chip_id) {
case CYBER9525DVD:
k = 2560 * Kb;
break;
default:
- tmp = read3X4(SPR) & 0x0F;
+ tmp = read3X4(par, SPR) & 0x0F;
switch (tmp) {
case 0x01:
@@ -774,7 +832,7 @@ static unsigned int __devinit get_memsize(void)
break;
case 0x0E: /* XP */
- tmp2 = read3C4(0xC1);
+ tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
switch (tmp2) {
case 0x00:
k = 20 * Mb;
@@ -812,26 +870,67 @@ static unsigned int __devinit get_memsize(void)
static int tridentfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
+ struct tridentfb_par *par = info->par;
int bpp = var->bits_per_pixel;
+ int line_length;
+ int ramdac = 230000; /* 230MHz for most 3D chips */
debug("enter\n");
/* check color depth */
if (bpp == 24)
bpp = var->bits_per_pixel = 32;
+ if (bpp != 8 && bpp != 16 && bpp != 32)
+ return -EINVAL;
+ if (par->chip_id == TGUI9440 && bpp == 32)
+ return -EINVAL;
/* check whether resolution fits on panel and in memory */
- if (flatpanel && nativex && var->xres > nativex)
+ if (par->flatpanel && nativex && var->xres > nativex)
+ return -EINVAL;
+ /* various resolution checks */
+ var->xres = (var->xres + 7) & ~0x7;
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+ if (var->xres_virtual > 4095 || var->yres > 2048)
return -EINVAL;
- if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len)
+ /* prevent from position overflow for acceleration */
+ if (var->yres_virtual > 0xffff)
+ return -EINVAL;
+ line_length = var->xres_virtual * bpp / 8;
+
+ if (!is3Dchip(par->chip_id) &&
+ !(info->flags & FBINFO_HWACCEL_DISABLED)) {
+ /* acceleration requires line length to be power of 2 */
+ if (line_length <= 512)
+ var->xres_virtual = 512 * 8 / bpp;
+ else if (line_length <= 1024)
+ var->xres_virtual = 1024 * 8 / bpp;
+ else if (line_length <= 2048)
+ var->xres_virtual = 2048 * 8 / bpp;
+ else if (line_length <= 4096)
+ var->xres_virtual = 4096 * 8 / bpp;
+ else if (line_length <= 8192)
+ var->xres_virtual = 8192 * 8 / bpp;
+ else
+ return -EINVAL;
+
+ line_length = var->xres_virtual * bpp / 8;
+ }
+
+ /* datasheet specifies how to set panning only up to 4 MB */
+ if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
+ var->yres_virtual = ((4 << 20) / line_length) + var->yres;
+
+ if (line_length * var->yres_virtual > info->fix.smem_len)
return -EINVAL;
switch (bpp) {
case 8:
var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- var->red.length = 6;
- var->green.length = 6;
- var->blue.length = 6;
+ var->red.length = 8;
+ var->green = var->red;
+ var->blue = var->red;
break;
case 16:
var->red.offset = 11;
@@ -852,6 +951,33 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
default:
return -EINVAL;
}
+
+ if (is_xp(par->chip_id))
+ ramdac = 350000;
+
+ switch (par->chip_id) {
+ case TGUI9440:
+ ramdac = (bpp >= 16) ? 45000 : 90000;
+ break;
+ case CYBER9320:
+ case TGUI9660:
+ ramdac = 135000;
+ break;
+ case PROVIDIA9685:
+ case CYBER9388:
+ case CYBER9382:
+ case CYBER9385:
+ ramdac = 170000;
+ break;
+ }
+
+ /* The clock is doubled for 32 bpp */
+ if (bpp == 32)
+ ramdac /= 2;
+
+ if (PICOS2KHZ(var->pixclock) > ramdac)
+ return -EINVAL;
+
debug("exit\n");
return 0;
@@ -862,25 +988,31 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
static int tridentfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
+ struct tridentfb_par *par = info->par;
unsigned int offset;
debug("enter\n");
- offset = (var->xoffset + (var->yoffset * var->xres))
+ offset = (var->xoffset + (var->yoffset * var->xres_virtual))
* var->bits_per_pixel / 32;
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- set_screen_start(offset);
+ set_screen_start(par, offset);
debug("exit\n");
return 0;
}
-#define shadowmode_on() write3CE(CyberControl, read3CE(CyberControl) | 0x81)
-#define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E)
+static inline void shadowmode_on(struct tridentfb_par *par)
+{
+ write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
+}
+
+static inline void shadowmode_off(struct tridentfb_par *par)
+{
+ write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
+}
/* Set the hardware to the requested video mode */
static int tridentfb_set_par(struct fb_info *info)
{
- struct tridentfb_par *par = (struct tridentfb_par *)(info->par);
+ struct tridentfb_par *par = info->par;
u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
struct fb_var_screeninfo *var = &info->var;
@@ -891,58 +1023,73 @@ static int tridentfb_set_par(struct fb_info *info)
debug("enter\n");
hdispend = var->xres / 8 - 1;
hsyncstart = (var->xres + var->right_margin) / 8;
- hsyncend = var->hsync_len / 8;
- htotal =
- (var->xres + var->left_margin + var->right_margin +
- var->hsync_len) / 8 - 10;
+ hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
+ htotal = (var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) / 8 - 5;
hblankstart = hdispend + 1;
- hblankend = htotal + 5;
+ hblankend = htotal + 3;
vdispend = var->yres - 1;
vsyncstart = var->yres + var->lower_margin;
- vsyncend = var->vsync_len;
- vtotal = var->upper_margin + vsyncstart + vsyncend - 2;
- vblankstart = var->yres;
- vblankend = vtotal + 2;
+ vsyncend = vsyncstart + var->vsync_len;
+ vtotal = var->upper_margin + vsyncend - 2;
+ vblankstart = vdispend + 1;
+ vblankend = vtotal;
+
+ if (info->var.vmode & FB_VMODE_INTERLACED) {
+ vtotal /= 2;
+ vdispend /= 2;
+ vsyncstart /= 2;
+ vsyncend /= 2;
+ vblankstart /= 2;
+ vblankend /= 2;
+ }
- crtc_unlock();
- write3CE(CyberControl, 8);
+ enable_mmio(par);
+ crtc_unlock(par);
+ write3CE(par, CyberControl, 8);
+ tmp = 0xEB;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ tmp &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ tmp &= ~0x80;
- if (flatpanel && var->xres < nativex) {
+ if (par->flatpanel && var->xres < nativex) {
/*
* on flat panels with native size larger
* than requested resolution decide whether
* we stretch or center
*/
- t_outb(0xEB, 0x3C2);
+ t_outb(par, tmp | 0xC0, VGA_MIS_W);
- shadowmode_on();
+ shadowmode_on(par);
if (center)
- screen_center();
+ screen_center(par);
else if (stretch)
- screen_stretch();
+ screen_stretch(par);
} else {
- t_outb(0x2B, 0x3C2);
- write3CE(CyberControl, 8);
+ t_outb(par, tmp, VGA_MIS_W);
+ write3CE(par, CyberControl, 8);
}
/* vertical timing values */
- write3X4(CRTVTotal, vtotal & 0xFF);
- write3X4(CRTVDispEnd, vdispend & 0xFF);
- write3X4(CRTVSyncStart, vsyncstart & 0xFF);
- write3X4(CRTVSyncEnd, (vsyncend & 0x0F));
- write3X4(CRTVBlankStart, vblankstart & 0xFF);
- write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ );
+ write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
+ write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
+ write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
+ write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
+ write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
+ write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
/* horizontal timing values */
- write3X4(CRTHTotal, htotal & 0xFF);
- write3X4(CRTHDispEnd, hdispend & 0xFF);
- write3X4(CRTHSyncStart, hsyncstart & 0xFF);
- write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
- write3X4(CRTHBlankStart, hblankstart & 0xFF);
- write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ );
+ write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
+ write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
+ write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
+ write3X4(par, VGA_CRTC_H_SYNC_END,
+ (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+ write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
+ write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
/* higher bits of vertical timing values */
tmp = 0x10;
@@ -954,39 +1101,43 @@ static int tridentfb_set_par(struct fb_info *info)
if (vtotal & 0x200) tmp |= 0x20;
if (vdispend & 0x200) tmp |= 0x40;
if (vsyncstart & 0x200) tmp |= 0x80;
- write3X4(CRTOverflow, tmp);
+ write3X4(par, VGA_CRTC_OVERFLOW, tmp);
- tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */
+ tmp = read3X4(par, CRTHiOrd) & 0x07;
+ tmp |= 0x08; /* line compare bit 10 */
if (vtotal & 0x400) tmp |= 0x80;
if (vblankstart & 0x400) tmp |= 0x40;
if (vsyncstart & 0x400) tmp |= 0x20;
if (vdispend & 0x400) tmp |= 0x10;
- write3X4(CRTHiOrd, tmp);
+ write3X4(par, CRTHiOrd, tmp);
- tmp = 0;
- if (htotal & 0x800) tmp |= 0x800 >> 11;
- if (hblankstart & 0x800) tmp |= 0x800 >> 7;
- write3X4(HorizOverflow, tmp);
+ tmp = (htotal >> 8) & 0x01;
+ tmp |= (hdispend >> 7) & 0x02;
+ tmp |= (hsyncstart >> 5) & 0x08;
+ tmp |= (hblankstart >> 4) & 0x10;
+ write3X4(par, HorizOverflow, tmp);
tmp = 0x40;
if (vblankstart & 0x200) tmp |= 0x20;
//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */
- write3X4(CRTMaxScanLine, tmp);
+ write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
- write3X4(CRTLineCompare, 0xFF);
- write3X4(CRTPRowScan, 0);
- write3X4(CRTModeControl, 0xC3);
+ write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
+ write3X4(par, VGA_CRTC_PRESET_ROW, 0);
+ write3X4(par, VGA_CRTC_MODE, 0xC3);
- write3X4(LinearAddReg, 0x20); /* enable linear addressing */
+ write3X4(par, LinearAddReg, 0x20); /* enable linear addressing */
tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
- write3X4(CRTCModuleTest, tmp); /* enable access extended memory */
-
- write3X4(GraphEngReg, 0x80); /* enable GE for text acceleration */
+ /* enable access extended memory */
+ write3X4(par, CRTCModuleTest, tmp);
+ tmp = read3CE(par, MiscIntContReg) & ~0x4;
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ tmp |= 0x4;
+ write3CE(par, MiscIntContReg, tmp);
-#ifdef CONFIG_FB_TRIDENT_ACCEL
- acc->init_accel(info->var.xres, bpp);
-#endif
+ /* enable GE for text acceleration */
+ write3X4(par, GraphEngReg, 0x80);
switch (bpp) {
case 8:
@@ -1003,57 +1154,59 @@ static int tridentfb_set_par(struct fb_info *info)
break;
}
- write3X4(PixelBusReg, tmp);
+ write3X4(par, PixelBusReg, tmp);
- tmp = 0x10;
- if (chipcyber)
+ tmp = read3X4(par, DRAMControl);
+ if (!is_oldprotect(par->chip_id))
+ tmp |= 0x10;
+ if (iscyber(par->chip_id))
tmp |= 0x20;
- write3X4(DRAMControl, tmp); /* both IO, linear enable */
-
- write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40);
- write3X4(Performance, 0x92);
- write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */
+ write3X4(par, DRAMControl, tmp); /* both IO, linear enable */
+
+ write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
+ if (!is_xp(par->chip_id))
+ write3X4(par, Performance, read3X4(par, Performance) | 0x10);
+ /* MMIO & PCI read and write burst enable */
+ if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
+ write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
+
+ vga_mm_wseq(par->io_virt, 0, 3);
+ vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
+ /* enable 4 maps because needed in chain4 mode */
+ vga_mm_wseq(par->io_virt, 2, 0x0F);
+ vga_mm_wseq(par->io_virt, 3, 0);
+ vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
/* convert from picoseconds to kHz */
vclk = PICOS2KHZ(info->var.pixclock);
- if (bpp == 32)
+
+ /* divide clock by 2 if 32bpp chain4 mode display and CPU path */
+ tmp = read3CE(par, MiscExtFunc) & 0xF0;
+ if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
+ tmp |= 8;
vclk *= 2;
- set_vclk(vclk);
-
- write3C4(0, 3);
- write3C4(1, 1); /* set char clock 8 dots wide */
- write3C4(2, 0x0F); /* enable 4 maps because needed in chain4 mode */
- write3C4(3, 0);
- write3C4(4, 0x0E); /* memory mode enable bitmaps ?? */
-
- write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12); /* divide clock by 2 if 32bpp */
- /* chain4 mode display and CPU path */
- write3CE(0x5, 0x40); /* no CGA compat, allow 256 col */
- write3CE(0x6, 0x05); /* graphics mode */
- write3CE(0x7, 0x0F); /* planes? */
-
- if (chip_id == CYBERBLADEXPAi1) {
- /* This fixes snow-effect in 32 bpp */
- write3X4(CRTHSyncStart, 0x84);
}
+ set_vclk(par, vclk);
+ write3CE(par, MiscExtFunc, tmp | 0x12);
+ write3CE(par, 0x5, 0x40); /* no CGA compat, allow 256 col */
+ write3CE(par, 0x6, 0x05); /* graphics mode */
+ write3CE(par, 0x7, 0x0F); /* planes? */
- writeAttr(0x10, 0x41); /* graphics mode and support 256 color modes */
- writeAttr(0x12, 0x0F); /* planes */
- writeAttr(0x13, 0); /* horizontal pel panning */
+ /* graphics mode and support 256 color modes */
+ writeAttr(par, 0x10, 0x41);
+ writeAttr(par, 0x12, 0x0F); /* planes */
+ writeAttr(par, 0x13, 0); /* horizontal pel panning */
/* colors */
for (tmp = 0; tmp < 0x10; tmp++)
- writeAttr(tmp, tmp);
- readb(par->io_virt + CRT + 0x0A); /* flip-flop to index */
- t_outb(0x20, 0x3C0); /* enable attr */
+ writeAttr(par, tmp, tmp);
+ fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
+ t_outb(par, 0x20, VGA_ATT_W); /* enable attr */
switch (bpp) {
case 8:
tmp = 0;
break;
- case 15:
- tmp = 0x10;
- break;
case 16:
tmp = 0x30;
break;
@@ -1063,19 +1216,23 @@ static int tridentfb_set_par(struct fb_info *info)
break;
}
- t_inb(0x3C8);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_inb(0x3C6);
- t_outb(tmp, 0x3C6);
- t_inb(0x3C8);
-
- if (flatpanel)
- set_number_of_lines(info->var.yres);
- set_lwidth(info->var.xres * bpp / (4 * 16));
+ t_inb(par, VGA_PEL_IW);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_MSK);
+ t_outb(par, tmp, VGA_PEL_MSK);
+ t_inb(par, VGA_PEL_IW);
+
+ if (par->flatpanel)
+ set_number_of_lines(par, info->var.yres);
+ info->fix.line_length = info->var.xres_virtual * bpp / 8;
+ set_lwidth(par, info->fix.line_length / 8);
+
+ if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+ par->init_accel(par, info->var.xres_virtual, bpp);
+
info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- info->fix.line_length = info->var.xres * (bpp >> 3);
info->cmap.len = (bpp == 8) ? 256 : 16;
debug("exit\n");
return 0;
@@ -1087,17 +1244,18 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info)
{
int bpp = info->var.bits_per_pixel;
+ struct tridentfb_par *par = info->par;
if (regno >= info->cmap.len)
return 1;
if (bpp == 8) {
- t_outb(0xFF, 0x3C6);
- t_outb(regno, 0x3C8);
+ t_outb(par, 0xFF, VGA_PEL_MSK);
+ t_outb(par, regno, VGA_PEL_IW);
- t_outb(red >> 10, 0x3C9);
- t_outb(green >> 10, 0x3C9);
- t_outb(blue >> 10, 0x3C9);
+ t_outb(par, red >> 10, VGA_PEL_D);
+ t_outb(par, green >> 10, VGA_PEL_D);
+ t_outb(par, blue >> 10, VGA_PEL_D);
} else if (regno < 16) {
if (bpp == 16) { /* RGB 565 */
@@ -1108,28 +1266,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
col |= col << 16;
((u32 *)(info->pseudo_palette))[regno] = col;
} else if (bpp == 32) /* ARGB 8888 */
- ((u32*)info->pseudo_palette)[regno] =
+ ((u32 *)info->pseudo_palette)[regno] =
((transp & 0xFF00) << 16) |
((red & 0xFF00) << 8) |
((green & 0xFF00)) |
((blue & 0xFF00) >> 8);
}
-/* debug("exit\n"); */
return 0;
}
-/* Try blanking the screen.For flat panels it does nothing */
+/* Try blanking the screen. For flat panels it does nothing */
static int tridentfb_blank(int blank_mode, struct fb_info *info)
{
unsigned char PMCont, DPMSCont;
+ struct tridentfb_par *par = info->par;
debug("enter\n");
- if (flatpanel)
+ if (par->flatpanel)
return 0;
- t_outb(0x04, 0x83C8); /* Read DPMS Control */
- PMCont = t_inb(0x83C6) & 0xFC;
- DPMSCont = read3CE(PowerStatus) & 0xFC;
+ t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
+ PMCont = t_inb(par, 0x83C6) & 0xFC;
+ DPMSCont = read3CE(par, PowerStatus) & 0xFC;
switch (blank_mode) {
case FB_BLANK_UNBLANK:
/* Screen: On, HSync: On, VSync: On */
@@ -1155,9 +1313,9 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
break;
}
- write3CE(PowerStatus, DPMSCont);
- t_outb(4, 0x83C8);
- t_outb(PMCont, 0x83C6);
+ write3CE(par, PowerStatus, DPMSCont);
+ t_outb(par, 4, 0x83C8);
+ t_outb(par, PMCont, 0x83C6);
debug("exit\n");
@@ -1174,33 +1332,46 @@ static struct fb_ops tridentfb_ops = {
.fb_set_par = tridentfb_set_par,
.fb_fillrect = tridentfb_fillrect,
.fb_copyarea = tridentfb_copyarea,
- .fb_imageblit = cfb_imageblit,
+ .fb_imageblit = tridentfb_imageblit,
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+ .fb_sync = tridentfb_sync,
+#endif
};
-static int __devinit trident_pci_probe(struct pci_dev * dev,
- const struct pci_device_id * id)
+static int __devinit trident_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
int err;
unsigned char revision;
+ struct fb_info *info;
+ struct tridentfb_par *default_par;
+ int chip3D;
+ int chip_id;
err = pci_enable_device(dev);
if (err)
return err;
- chip_id = id->device;
+ info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
+ if (!info)
+ return -ENOMEM;
+ default_par = info->par;
- if (chip_id == CYBERBLADEi1)
- output("*** Please do use cyblafb, Cyberblade/i1 support "
- "will soon be removed from tridentfb!\n");
+ chip_id = id->device;
+#ifndef CONFIG_FB_TRIDENT_ACCEL
+ noaccel = 1;
+#endif
/* If PCI id is 0x9660 then further detect chip type */
if (chip_id == TGUI9660) {
- outb(RevisionID, 0x3C4);
- revision = inb(0x3C5);
+ revision = vga_io_rseq(RevisionID);
switch (revision) {
+ case 0x21:
+ chip_id = PROVIDIA9685;
+ break;
case 0x22:
case 0x23:
chip_id = CYBER9397;
@@ -1229,123 +1400,170 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
}
chip3D = is3Dchip(chip_id);
- chipcyber = iscyber(chip_id);
if (is_xp(chip_id)) {
- acc = &accel_xp;
+ default_par->init_accel = xp_init_accel;
+ default_par->wait_engine = xp_wait_engine;
+ default_par->fill_rect = xp_fill_rect;
+ default_par->copy_rect = xp_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
} else if (is_blade(chip_id)) {
- acc = &accel_blade;
- } else {
- acc = &accel_image;
+ default_par->init_accel = blade_init_accel;
+ default_par->wait_engine = blade_wait_engine;
+ default_par->fill_rect = blade_fill_rect;
+ default_par->copy_rect = blade_copy_rect;
+ default_par->image_blit = blade_image_blit;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
+ } else if (chip3D) { /* 3DImage family left */
+ default_par->init_accel = image_init_accel;
+ default_par->wait_engine = image_wait_engine;
+ default_par->fill_rect = image_fill_rect;
+ default_par->copy_rect = image_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
+ } else { /* TGUI 9440/96XX family */
+ default_par->init_accel = tgui_init_accel;
+ default_par->wait_engine = xp_wait_engine;
+ default_par->fill_rect = tgui_fill_rect;
+ default_par->copy_rect = tgui_copy_rect;
+ tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
}
- /* acceleration is on by default for 3D chips */
- defaultaccel = chip3D && !noaccel;
-
- fb_info.par = &default_par;
+ default_par->chip_id = chip_id;
/* setup MMIO region */
tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
- tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000;
+ tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
- if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) {
+ if (!request_mem_region(tridentfb_fix.mmio_start,
+ tridentfb_fix.mmio_len, "tridentfb")) {
debug("request_region failed!\n");
+ framebuffer_release(info);
return -1;
}
- default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
+ tridentfb_fix.mmio_len);
- if (!default_par.io_virt) {
+ if (!default_par->io_virt) {
debug("ioremap failed\n");
err = -1;
goto out_unmap1;
}
- enable_mmio();
+ enable_mmio(default_par);
/* setup framebuffer memory */
tridentfb_fix.smem_start = pci_resource_start(dev, 0);
- tridentfb_fix.smem_len = get_memsize();
+ tridentfb_fix.smem_len = get_memsize(default_par);
- if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
+ if (!request_mem_region(tridentfb_fix.smem_start,
+ tridentfb_fix.smem_len, "tridentfb")) {
debug("request_mem_region failed!\n");
- disable_mmio();
+ disable_mmio(info->par);
err = -1;
goto out_unmap1;
}
- fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
- tridentfb_fix.smem_len);
+ info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
+ tridentfb_fix.smem_len);
- if (!fb_info.screen_base) {
+ if (!info->screen_base) {
debug("ioremap failed\n");
err = -1;
goto out_unmap2;
}
- output("%s board found\n", pci_name(dev));
- displaytype = get_displaytype();
+ default_par->flatpanel = is_flatpanel(default_par);
- if (flatpanel)
- nativex = get_nativex();
+ if (default_par->flatpanel)
+ nativex = get_nativex(default_par);
- fb_info.fix = tridentfb_fix;
- fb_info.fbops = &tridentfb_ops;
+ info->fix = tridentfb_fix;
+ info->fbops = &tridentfb_ops;
+ info->pseudo_palette = default_par->pseudo_pal;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ if (!noaccel && default_par->init_accel) {
+ info->flags &= ~FBINFO_HWACCEL_DISABLED;
+ info->flags |= FBINFO_HWACCEL_COPYAREA;
+ info->flags |= FBINFO_HWACCEL_FILLRECT;
+ } else
+ info->flags |= FBINFO_HWACCEL_DISABLED;
- fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-#ifdef CONFIG_FB_TRIDENT_ACCEL
- fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
-#endif
- fb_info.pseudo_palette = pseudo_pal;
+ info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ err = -ENOMEM;
+ goto out_unmap2;
+ }
+
+ info->pixmap.size = 4096;
+ info->pixmap.buf_align = 4;
+ info->pixmap.scan_align = 1;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
- if (!fb_find_mode(&default_var, &fb_info,
+ if (default_par->image_blit) {
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
+ info->pixmap.scan_align = 4;
+ }
+
+ if (noaccel) {
+ printk(KERN_DEBUG "disabling acceleration\n");
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ info->pixmap.scan_align = 1;
+ }
+
+ if (!fb_find_mode(&info->var, info,
mode_option, NULL, 0, NULL, bpp)) {
err = -EINVAL;
goto out_unmap2;
}
- err = fb_alloc_cmap(&fb_info.cmap, 256, 0);
+ err = fb_alloc_cmap(&info->cmap, 256, 0);
if (err < 0)
goto out_unmap2;
- if (defaultaccel && acc)
- default_var.accel_flags |= FB_ACCELF_TEXT;
- else
- default_var.accel_flags &= ~FB_ACCELF_TEXT;
- default_var.activate |= FB_ACTIVATE_NOW;
- fb_info.var = default_var;
- fb_info.device = &dev->dev;
- if (register_framebuffer(&fb_info) < 0) {
- printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
- fb_dealloc_cmap(&fb_info.cmap);
+ info->var.activate |= FB_ACTIVATE_NOW;
+ info->device = &dev->dev;
+ if (register_framebuffer(info) < 0) {
+ printk(KERN_ERR "tridentfb: could not register framebuffer\n");
+ fb_dealloc_cmap(&info->cmap);
err = -EINVAL;
goto out_unmap2;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
- fb_info.node, fb_info.fix.id, default_var.xres,
- default_var.yres, default_var.bits_per_pixel);
+ info->node, info->fix.id, info->var.xres,
+ info->var.yres, info->var.bits_per_pixel);
+
+ pci_set_drvdata(dev, info);
return 0;
out_unmap2:
- if (fb_info.screen_base)
- iounmap(fb_info.screen_base);
+ kfree(info->pixmap.addr);
+ if (info->screen_base)
+ iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
- disable_mmio();
+ disable_mmio(info->par);
out_unmap1:
- if (default_par.io_virt)
- iounmap(default_par.io_virt);
+ if (default_par->io_virt)
+ iounmap(default_par->io_virt);
release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ framebuffer_release(info);
return err;
}
static void __devexit trident_pci_remove(struct pci_dev *dev)
{
- struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
- unregister_framebuffer(&fb_info);
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct tridentfb_par *par = info->par;
+
+ unregister_framebuffer(info);
iounmap(par->io_virt);
- iounmap(fb_info.screen_base);
+ iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+ pci_set_drvdata(dev, NULL);
+ kfree(info->pixmap.addr);
+ framebuffer_release(info);
}
/* List of boards that we are trying to support */
@@ -1358,6 +1576,7 @@ static struct pci_device_id trident_devices[] = {
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -1399,9 +1618,9 @@ static int __init tridentfb_setup(char *options)
if (!strncmp(opt, "noaccel", 7))
noaccel = 1;
else if (!strncmp(opt, "fp", 2))
- displaytype = DISPLAY_FP;
+ fp = 1;
else if (!strncmp(opt, "crt", 3))
- displaytype = DISPLAY_CRT;
+ fp = 0;
else if (!strncmp(opt, "bpp=", 4))
bpp = simple_strtoul(opt + 4, NULL, 0);
else if (!strncmp(opt, "center", 6))
@@ -1430,7 +1649,6 @@ static int __init tridentfb_init(void)
return -ENODEV;
tridentfb_setup(option);
#endif
- output("Trident framebuffer %s initializing\n", VERSION);
return pci_register_driver(&tridentfb_pci_driver);
}
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index cdbb56edb6c..50744229c7a 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -2054,8 +2054,8 @@ MODULE_PARM_DESC(maxhf,
module_param(maxvf, ushort, 0);
MODULE_PARM_DESC(maxvf,
"Maximum vertical frequency [Hz], overrides EDID data");
-module_param_named(mode, mode_option, charp, 0);
-MODULE_PARM_DESC(mode,
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option,
"Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
module_param(vbemode, ushort, 0);
MODULE_PARM_DESC(vbemode,
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 072638a9528..93fe08d6c78 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -443,19 +443,29 @@ static int vfb_mmap(struct fb_info *info,
}
#ifndef MODULE
+/*
+ * The virtual framebuffer driver is only enabled if explicitly
+ * requested by passing 'video=vfb:' (or any actual options).
+ */
static int __init vfb_setup(char *options)
{
char *this_opt;
+ vfb_enable = 0;
+
+ if (!options)
+ return 1;
+
vfb_enable = 1;
- if (!options || !*options)
+ if (!*options)
return 1;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
- if (!strncmp(this_opt, "disable", 7))
+ /* Test disable for backwards compatibility */
+ if (!strcmp(this_opt, "disable"))
vfb_enable = 0;
}
return 1;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 9b3c5923365..e31bca8a0cb 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -26,18 +26,6 @@
#include <asm/io.h>
#include <video/vga.h>
-#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */
-#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */
-
-#define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */
-#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */
-#define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */
-#define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */
-#define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */
-
-#define dac_reg (VGA_PEL_IW)
-#define dac_val (VGA_PEL_D)
-
#define VGA_FB_PHYS 0xA0000
#define VGA_FB_PHYS_LEN 65536
@@ -108,7 +96,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
.visual = FB_VISUAL_PSEUDOCOLOR,
.xpanstep = 8,
.ypanstep = 1,
- .line_length = 640/8,
+ .line_length = 640 / 8,
.accel = FB_ACCEL_NONE
};
@@ -135,23 +123,22 @@ static inline int setmode(int mode)
{
int oldmode;
- vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX);
- oldmode = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, mode);
+ oldmode = vga_io_rgfx(VGA_GFX_MODE);
+ vga_io_w(VGA_GFX_D, mode);
return oldmode;
}
/* Select the Bit Mask Register and return its value. */
static inline int selectmask(void)
{
- return vga_io_rgfx(BIT_MASK_INDEX);
+ return vga_io_rgfx(VGA_GFX_BIT_MASK);
}
/* Set the value of the Bit Mask Register. It must already have been
selected with selectmask(). */
static inline void setmask(int mask)
{
- vga_io_w(GRAPHICS_DATA_REG, mask);
+ vga_io_w(VGA_GFX_D, mask);
}
/* Set the Data Rotate Register and return its old value.
@@ -161,9 +148,8 @@ static inline int setop(int op)
{
int oldop;
- vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX);
- oldop = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, op);
+ oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
+ vga_io_w(VGA_GFX_D, op);
return oldop;
}
@@ -173,9 +159,8 @@ static inline int setsr(int sr)
{
int oldsr;
- vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX);
- oldsr = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, sr);
+ oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
+ vga_io_w(VGA_GFX_D, sr);
return oldsr;
}
@@ -184,22 +169,21 @@ static inline int setcolor(int color)
{
int oldcolor;
- vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX);
- oldcolor = vga_io_r(GRAPHICS_DATA_REG);
- vga_io_w(GRAPHICS_DATA_REG, color);
+ oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
+ vga_io_w(VGA_GFX_D, color);
return oldcolor;
}
/* Return the value in the Graphics Address Register. */
static inline int getindex(void)
{
- return vga_io_r(GRAPHICS_ADDR_REG);
+ return vga_io_r(VGA_GFX_I);
}
/* Set the value in the Graphics Address Register. */
static inline void setindex(int index)
{
- vga_io_w(GRAPHICS_ADDR_REG, index);
+ vga_io_w(VGA_GFX_I, index);
}
static void vga16fb_pan_var(struct fb_info *info,
@@ -672,10 +656,10 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
- outb(regno, dac_reg);
- outb(red >> 10, dac_val);
- outb(green >> 10, dac_val);
- outb(blue >> 10, dac_val);
+ outb(regno, VGA_PEL_IW);
+ outb(red >> 10, VGA_PEL_D);
+ outb(green >> 10, VGA_PEL_D);
+ outb(blue >> 10, VGA_PEL_D);
}
static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -719,28 +703,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var,
blanking code was originally by Huang shi chao, and modified by
Christoph Rimek (chrimek@toppoint.de) and todd j. derr
(tjd@barefoot.org) for Linux. */
-#define attrib_port VGA_ATC_IW
-#define seq_port_reg VGA_SEQ_I
-#define seq_port_val VGA_SEQ_D
-#define gr_port_reg VGA_GFX_I
-#define gr_port_val VGA_GFX_D
-#define video_misc_rd VGA_MIS_R
-#define video_misc_wr VGA_MIS_W
-#define vga_video_port_reg VGA_CRT_IC
-#define vga_video_port_val VGA_CRT_DC
static void vga_vesa_blank(struct vga16fb_par *par, int mode)
{
- unsigned char SeqCtrlIndex;
- unsigned char CrtCtrlIndex;
+ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+ unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
- //cli();
- SeqCtrlIndex = vga_io_r(seq_port_reg);
- CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
/* save original values of VGA controller registers */
if(!par->vesa_blanked) {
- par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd);
+ par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
//sti();
par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */
@@ -756,12 +727,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
/* assure that video is enabled */
/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
- //cli();
vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
/* test for vertical retrace in process.... */
if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
- vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef);
+ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
/*
* Set <End of vertical retrace> to minimum (0) and
@@ -769,12 +739,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
* Result: turn off vertical sync (VSync) pulse.
*/
if (mode & FB_BLANK_VSYNC_SUSPEND) {
- outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */
- outb_p(0xff,vga_video_port_val); /* maximum value */
- outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */
- outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */
- outb_p(0x07,vga_video_port_reg); /* Overflow */
- outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+ vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
+ vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
+ /* bits 9,10 of vert. retrace */
+ vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
}
if (mode & FB_BLANK_HSYNC_SUSPEND) {
@@ -783,29 +751,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
* <Start of horizontal Retrace> to maximum
* Result: turn off horizontal sync (HSync) pulse.
*/
- outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */
- outb_p(0xff,vga_video_port_val); /* maximum */
- outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
- outb_p(0x00,vga_video_port_val); /* minimum (0) */
+ vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
+ vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
}
/* restore both index registers */
- outb_p(SeqCtrlIndex,seq_port_reg);
- outb_p(CrtCtrlIndex,vga_video_port_reg);
- //sti();
+ outb_p(SeqCtrlIndex, VGA_SEQ_I);
+ outb_p(CrtCtrlIndex, VGA_CRT_IC);
}
static void vga_vesa_unblank(struct vga16fb_par *par)
{
- unsigned char SeqCtrlIndex;
- unsigned char CrtCtrlIndex;
+ unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
+ unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
- //cli();
- SeqCtrlIndex = vga_io_r(seq_port_reg);
- CrtCtrlIndex = vga_io_r(vga_video_port_reg);
-
/* restore original values of VGA controller registers */
- vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO);
+ vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
/* HorizontalTotal */
vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
@@ -827,9 +788,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
vga_io_wseq(0x01, par->vga_state.ClockingMode);
/* restore index/control registers */
- vga_io_w(seq_port_reg, SeqCtrlIndex);
- vga_io_w(vga_video_port_reg, CrtCtrlIndex);
- //sti();
+ vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
+ vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
}
static void vga_pal_blank(void)
@@ -837,10 +797,10 @@ static void vga_pal_blank(void)
int i;
for (i=0; i<16; i++) {
- outb_p (i, dac_reg) ;
- outb_p (0, dac_val) ;
- outb_p (0, dac_val) ;
- outb_p (0, dac_val) ;
+ outb_p(i, VGA_PEL_IW);
+ outb_p(0, VGA_PEL_D);
+ outb_p(0, VGA_PEL_D);
+ outb_p(0, VGA_PEL_D);
}
}
@@ -1087,12 +1047,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
width = x2 - dx;
height = y2 - dy;
+ if (sx + dx < old_dx || sy + dy < old_dy)
+ return;
+
/* update sx1,sy1 */
sx += (dx - old_dx);
sy += (dy - old_dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
+ if (sx + width > vxres || sy + height > vyres)
return;
switch (info->fix.type) {
@@ -1482,6 +1445,7 @@ static void __exit vga16fb_exit(void)
platform_driver_unregister(&vga16fb_driver);
}
+MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
MODULE_LICENSE("GPL");
module_init(vga16fb_init);
module_exit(vga16fb_exit);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index ccb78f66c2b..48399e134c0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -788,8 +788,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# V850 Architecture
-
# XTENSA Architecture
#
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 25b352b664d..edd305a64e6 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -119,8 +119,6 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
# SPARC64 Architecture
-# V850 Architecture
-
# XTENSA Architecture
# Architecture Independant
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 591bc29b55f..d4427cb8697 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -610,6 +610,7 @@ static ssize_t show_target_kb(struct sys_device *dev, char *buf)
}
static ssize_t store_target_kb(struct sys_device *dev,
+ struct sysdev_attribute *attr,
const char *buf,
size_t count)
{
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 332dd63750a..0e0c28574af 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -734,6 +734,33 @@ static void restore_cpu_ipis(unsigned int cpu)
}
}
+/* Clear an irq's pending state, in preparation for polling on it */
+void xen_clear_irq_pending(int irq)
+{
+ int evtchn = evtchn_from_irq(irq);
+
+ if (VALID_EVTCHN(evtchn))
+ clear_evtchn(evtchn);
+}
+
+/* Poll waiting for an irq to become pending. In the usual case, the
+ irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq)
+{
+ evtchn_port_t evtchn = evtchn_from_irq(irq);
+
+ if (VALID_EVTCHN(evtchn)) {
+ struct sched_poll poll;
+
+ poll.nr_ports = 1;
+ poll.timeout = 0;
+ poll.ports = &evtchn;
+
+ if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0)
+ BUG();
+ }
+}
+
void xen_irq_resume(void)
{
unsigned int cpu, irq, evtchn;
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 5b546e365f0..a5bc91ae6ff 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -63,11 +63,12 @@ static int xen_suspend(void *data)
gnttab_resume();
xen_mm_unpin_all();
- device_power_up();
+ device_power_up(PMSG_RESUME);
if (!*cancelled) {
xen_irq_resume();
xen_console_resume();
+ xen_timer_resume();
}
return 0;
@@ -107,12 +108,13 @@ static void do_suspend(void)
goto out;
}
- if (!cancelled)
+ if (!cancelled) {
+ xen_arch_resume();
xenbus_resume();
- else
+ } else
xenbus_suspend_cancel();
- device_resume();
+ device_resume(PMSG_RESUME);
/* Make sure timer events get retriggered on all CPUs */
clock_was_set();
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 3da712cc770..5290552d2ef 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -15,7 +15,6 @@
#include <linux/zorro.h>
#include <linux/stat.h>
#include <linux/string.h>
-#include <linux/fs.h>
#include "zorro.h"